Browse Source
Replace everything under AP_HAL_AVR with a README.md file pointing to the correct branch for AVR support.master
111 changed files with 1 additions and 6695 deletions
@ -1,20 +0,0 @@
@@ -1,20 +0,0 @@
|
||||
|
||||
#ifndef __AP_HAL_AVR_H__ |
||||
#define __AP_HAL_AVR_H__ |
||||
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
|
||||
#if CONFIG_HAL_BOARD == HAL_BOARD_APM1 || CONFIG_HAL_BOARD == HAL_BOARD_APM2 |
||||
/**
|
||||
* This module exports AP_HAL::HAL instances only. |
||||
* All internal drivers must conform to AP_HAL interfaces |
||||
* and not expose implementation details. |
||||
*/ |
||||
|
||||
#include "HAL_AVR_APM1_Class.h" |
||||
#include "HAL_AVR_APM2_Class.h" |
||||
|
||||
#endif // CONFIG_HAL_BOARD
|
||||
|
||||
#endif // __AP_HAL_AVR_H__
|
||||
|
@ -1,32 +0,0 @@
@@ -1,32 +0,0 @@
|
||||
|
||||
#ifndef __AP_HAL_AVR_NAMESPACE_H__ |
||||
#define __AP_HAL_AVR_NAMESPACE_H__ |
||||
|
||||
namespace AP_HAL_AVR { |
||||
class HAL_AVR; |
||||
|
||||
class AVRUARTDriver; |
||||
class AVRI2CDriver; |
||||
class APM1SPIDeviceManager; |
||||
class APM2SPIDeviceManager; |
||||
class AVRSPI0DeviceDriver; |
||||
class AVRSPI2DeviceDriver; |
||||
class AVRSPI3DeviceDriver; |
||||
class ADCSource; |
||||
class AVRAnalogIn; |
||||
class AVREEPROMStorage; |
||||
class AVRGPIO; |
||||
class AVRDigitalSource; |
||||
class APM1RCInput; |
||||
class APM2RCInput; |
||||
class APM1RCOutput; |
||||
class APM2RCOutput; |
||||
class AVRScheduler; |
||||
class AVRTimer; |
||||
class AVRSemaphore; |
||||
class ISRRegistry; |
||||
class AVRUtil; |
||||
} |
||||
|
||||
#endif //__AP_HAL_AVR_NAMESPACE_H__
|
||||
|
@ -1,17 +0,0 @@
@@ -1,17 +0,0 @@
|
||||
|
||||
#ifndef __AP_HAL_AVR_PRIVATE_H__ |
||||
#define __AP_HAL_AVR_PRIVATE_H__ |
||||
|
||||
#include "UARTDriver.h" |
||||
#include "I2CDriver.h" |
||||
#include "SPIDriver.h" |
||||
#include "AnalogIn.h" |
||||
#include "Storage.h" |
||||
#include "GPIO.h" |
||||
#include "RCInput.h" |
||||
#include "RCOutput.h" |
||||
#include "Scheduler.h" |
||||
#include "Util.h" |
||||
#include "utility/ISRRegistry.h" |
||||
|
||||
#endif // __AP_HAL_AVR_PRIVATE_H__
|
@ -1,86 +0,0 @@
@@ -1,86 +0,0 @@
|
||||
|
||||
#ifndef __AP_HAL_AVR_ANALOG_IN_H__ |
||||
#define __AP_HAL_AVR_ANALOG_IN_H__ |
||||
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#include "AP_HAL_AVR_Namespace.h" |
||||
|
||||
#define AVR_INPUT_MAX_CHANNELS 12 |
||||
|
||||
class AP_HAL_AVR::ADCSource : public AP_HAL::AnalogSource { |
||||
public: |
||||
friend class AP_HAL_AVR::AVRAnalogIn; |
||||
/* pin designates the ADC input number, or when == AVR_ANALOG_PIN_VCC,
|
||||
* board vcc */ |
||||
ADCSource(uint8_t pin); |
||||
|
||||
/* implement AnalogSource virtual api: */ |
||||
float read_average(); |
||||
float read_latest(); |
||||
void set_pin(uint8_t p); |
||||
float voltage_average(); |
||||
float voltage_latest(); |
||||
float voltage_average_ratiometric(); |
||||
void set_stop_pin(uint8_t p); |
||||
void set_settle_time(uint16_t settle_time_ms);
|
||||
|
||||
/* implementation specific interface: */ |
||||
|
||||
/* new_sample(): called with value of ADC measurments, from interrput */ |
||||
void new_sample(uint16_t); |
||||
|
||||
/* setup_read(): called to setup ADC registers for next measurment,
|
||||
* from interrupt */ |
||||
void setup_read(); |
||||
|
||||
/* stop_read(): called to stop device measurement */ |
||||
void stop_read(); |
||||
|
||||
/* reading_settled(): called to check if we have read for long enough */ |
||||
bool reading_settled(); |
||||
|
||||
/* read_average: called to calculate and clear the internal average.
|
||||
* implements read_average(), unscaled. */ |
||||
float _read_average(); |
||||
|
||||
int16_t get_pin() { return _pin; }; |
||||
private: |
||||
/* following three are used from both an interrupt and normal thread */ |
||||
volatile uint8_t _sum_count; |
||||
volatile uint16_t _sum; |
||||
volatile uint16_t _latest; |
||||
float _last_average; |
||||
|
||||
/* _pin designates the ADC input mux for the sample */ |
||||
uint8_t _pin; |
||||
|
||||
/* _stop_pin designates a digital pin to use for
|
||||
enabling/disabling the analog device */ |
||||
uint8_t _stop_pin; |
||||
uint16_t _settle_time_ms; |
||||
uint32_t _read_start_time_ms; |
||||
}; |
||||
|
||||
/* AVRAnalogIn : a concrete class providing the implementations of the
|
||||
* timer event and the AP_HAL::AnalogIn interface */ |
||||
class AP_HAL_AVR::AVRAnalogIn : public AP_HAL::AnalogIn { |
||||
public: |
||||
AVRAnalogIn(); |
||||
void init(void* ap_hal_scheduler); |
||||
AP_HAL::AnalogSource* channel(int16_t n); |
||||
float board_voltage(void); |
||||
|
||||
protected:
|
||||
ADCSource* _create_channel(int16_t num); |
||||
void _register_channel(ADCSource*); |
||||
void _timer_event(void); |
||||
ADCSource* _channels[AVR_INPUT_MAX_CHANNELS]; |
||||
int16_t _num_channels; |
||||
int16_t _active_channel; |
||||
uint16_t _channel_repeat_count; |
||||
|
||||
private: |
||||
ADCSource _vcc; |
||||
}; |
||||
|
||||
#endif // __AP_HAL_AVR_ANALOG_IN_H__
|
@ -1,202 +0,0 @@
@@ -1,202 +0,0 @@
|
||||
/// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#if (CONFIG_HAL_BOARD == HAL_BOARD_APM1 || CONFIG_HAL_BOARD == HAL_BOARD_APM2) |
||||
|
||||
#include <avr/io.h> |
||||
#include <avr/interrupt.h> |
||||
|
||||
#include "AnalogIn.h" |
||||
using namespace AP_HAL_AVR; |
||||
|
||||
extern const AP_HAL::HAL& hal; |
||||
|
||||
ADCSource::ADCSource(uint8_t pin) : |
||||
_sum_count(0), |
||||
_sum(0), |
||||
_last_average(0), |
||||
_pin(ANALOG_INPUT_NONE), |
||||
_stop_pin(ANALOG_INPUT_NONE), |
||||
_settle_time_ms(0) |
||||
{ |
||||
set_pin(pin); |
||||
} |
||||
|
||||
float ADCSource::read_average() { |
||||
if (_pin == ANALOG_INPUT_BOARD_VCC) { |
||||
uint16_t v = (uint16_t) _read_average(); |
||||
return 1126400UL / v; |
||||
} else { |
||||
return _read_average(); |
||||
} |
||||
} |
||||
|
||||
float ADCSource::read_latest() { |
||||
uint8_t sreg = SREG; |
||||
cli(); |
||||
uint16_t latest = _latest; |
||||
SREG = sreg; |
||||
if (_pin == ANALOG_INPUT_BOARD_VCC) { |
||||
return 1126400UL / latest; |
||||
} else { |
||||
return latest; |
||||
} |
||||
} |
||||
|
||||
/*
|
||||
return voltage from 0.0 to 5.0V, scaled to Vcc |
||||
*/ |
||||
float ADCSource::voltage_average(void) |
||||
{ |
||||
float vcc_mV = hal.analogin->channel(ANALOG_INPUT_BOARD_VCC)->read_average(); |
||||
float v = read_average(); |
||||
// constrain Vcc reading so that a bad Vcc doesn't throw off
|
||||
// the reading of other sources too badly
|
||||
if (vcc_mV < 4000) { |
||||
vcc_mV = 4000; |
||||
} else if (vcc_mV > 6000) { |
||||
vcc_mV = 6000; |
||||
} |
||||
return v * vcc_mV * 9.765625e-7; // 9.765625e-7 = 1.0/(1024*1000)
|
||||
} |
||||
|
||||
/*
|
||||
return voltage from 0.0 to 5.0V, scaled to Vcc |
||||
*/ |
||||
float ADCSource::voltage_latest(void) |
||||
{ |
||||
if (_pin == ANALOG_INPUT_BOARD_VCC) { |
||||
return read_latest() * 0.001f; |
||||
} |
||||
float vcc_mV = hal.analogin->channel(ANALOG_INPUT_BOARD_VCC)->read_average(); |
||||
float v = read_latest(); |
||||
// constrain Vcc reading so that a bad Vcc doesn't throw off
|
||||
// the reading of other sources too badly
|
||||
if (vcc_mV < 4000) { |
||||
vcc_mV = 4000; |
||||
} else if (vcc_mV > 6000) { |
||||
vcc_mV = 6000; |
||||
} |
||||
return v * vcc_mV * 9.765625e-7; // 9.765625e-7 = 1.0/(1024*1000)
|
||||
} |
||||
|
||||
/*
|
||||
return voltage from 0.0 to 5.0V, assuming a ratiometric sensor. This |
||||
means the result is really a pseudo-voltage, that assumes the supply |
||||
voltage is exactly 5.0V. |
||||
*/ |
||||
float ADCSource::voltage_average_ratiometric(void) |
||||
{ |
||||
float v = read_average(); |
||||
return v * (5.0f / 1023.0f); |
||||
} |
||||
|
||||
void ADCSource::set_pin(uint8_t pin) { |
||||
if (pin != _pin) { |
||||
// ensure the pin is marked as an INPUT pin
|
||||
if (pin != ANALOG_INPUT_NONE && pin != ANALOG_INPUT_BOARD_VCC) { |
||||
int8_t dpin = hal.gpio->analogPinToDigitalPin(pin); |
||||
if (dpin != -1) { |
||||
// enable as input without a pull-up. This gives the
|
||||
// best results for our analog sensors
|
||||
hal.gpio->pinMode(dpin, HAL_GPIO_INPUT); |
||||
hal.gpio->write(dpin, 0); |
||||
} |
||||
} |
||||
uint8_t sreg = SREG; |
||||
cli(); |
||||
_sum = 0; |
||||
_sum_count = 0; |
||||
_last_average = 0; |
||||
_latest = 0; |
||||
_pin = pin; |
||||
SREG = sreg; |
||||
} |
||||
} |
||||
|
||||
void ADCSource::set_stop_pin(uint8_t pin) { |
||||
_stop_pin = pin; |
||||
} |
||||
|
||||
void ADCSource::set_settle_time(uint16_t settle_time_ms)
|
||||
{ |
||||
_settle_time_ms = settle_time_ms; |
||||
} |
||||
|
||||
/* read_average is called from the normal thread (not an interrupt). */ |
||||
float ADCSource::_read_average() { |
||||
uint16_t sum; |
||||
uint8_t sum_count; |
||||
|
||||
if (_sum_count == 0) { |
||||
// avoid blocking waiting for new samples
|
||||
return _last_average; |
||||
} |
||||
|
||||
/* Read and clear in a critical section */ |
||||
uint8_t sreg = SREG; |
||||
cli(); |
||||
|
||||
sum = _sum; |
||||
sum_count = _sum_count; |
||||
_sum = 0; |
||||
_sum_count = 0; |
||||
|
||||
SREG = sreg; |
||||
|
||||
float avg = sum / (float) sum_count; |
||||
|
||||
_last_average = avg; |
||||
return avg; |
||||
} |
||||
|
||||
void ADCSource::setup_read() { |
||||
if (_stop_pin != ANALOG_INPUT_NONE) { |
||||
uint8_t digital_pin = hal.gpio->analogPinToDigitalPin(_stop_pin); |
||||
hal.gpio->pinMode(digital_pin, HAL_GPIO_OUTPUT); |
||||
hal.gpio->write(digital_pin, 1); |
||||
} |
||||
if (_settle_time_ms != 0) { |
||||
_read_start_time_ms = hal.scheduler->millis(); |
||||
} |
||||
if (_pin == ANALOG_INPUT_BOARD_VCC) { |
||||
ADCSRB = (ADCSRB & ~(1 << MUX5)); |
||||
ADMUX = _BV(REFS0)|_BV(MUX4)|_BV(MUX3)|_BV(MUX2)|_BV(MUX1); |
||||
} else if (_pin == ANALOG_INPUT_NONE) { |
||||
/* noop */ |
||||
} else { |
||||
ADCSRB = (ADCSRB & ~(1 << MUX5)) | (((_pin >> 3) & 0x01) << MUX5); |
||||
ADMUX = _BV(REFS0) | (_pin & 0x07); |
||||
} |
||||
} |
||||
|
||||
void ADCSource::stop_read() { |
||||
if (_stop_pin != ANALOG_INPUT_NONE) { |
||||
uint8_t digital_pin = hal.gpio->analogPinToDigitalPin(_stop_pin); |
||||
hal.gpio->pinMode(digital_pin, HAL_GPIO_OUTPUT); |
||||
hal.gpio->write(digital_pin, 0); |
||||
} |
||||
} |
||||
|
||||
bool ADCSource::reading_settled()
|
||||
{ |
||||
if (_settle_time_ms != 0 && (hal.scheduler->millis() - _read_start_time_ms) < _settle_time_ms) { |
||||
return false; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
/* new_sample is called from an interrupt. It always has access to
|
||||
* _sum and _sum_count. Lock out the interrupts briefly with |
||||
* cli/sei to read these variables from outside an interrupt. */ |
||||
void ADCSource::new_sample(uint16_t sample) { |
||||
_sum += sample; |
||||
_latest = sample; |
||||
if (_sum_count >= 63) { |
||||
_sum >>= 1; |
||||
_sum_count = 32; |
||||
} else { |
||||
_sum_count++; |
||||
} |
||||
} |
||||
#endif |
@ -1,125 +0,0 @@
@@ -1,125 +0,0 @@
|
||||
/// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#if (CONFIG_HAL_BOARD == HAL_BOARD_APM1 || CONFIG_HAL_BOARD == HAL_BOARD_APM2) |
||||
|
||||
#include <avr/io.h> |
||||
#include <avr/interrupt.h> |
||||
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#include "AnalogIn.h" |
||||
using namespace AP_HAL_AVR; |
||||
|
||||
extern const AP_HAL::HAL& hal; |
||||
|
||||
/* CHANNEL_READ_REPEAT: how many reads on a channel before using the value.
|
||||
* This seems to be determined empirically */ |
||||
#define CHANNEL_READ_REPEAT 2 |
||||
|
||||
AVRAnalogIn::AVRAnalogIn() : |
||||
_vcc(ADCSource(ANALOG_INPUT_BOARD_VCC)) |
||||
{} |
||||
|
||||
void AVRAnalogIn::init(void* machtnichts)
|
||||
{ |
||||
/* Register AVRAnalogIn::_timer_event with the scheduler. */ |
||||
hal.scheduler->register_timer_process(FUNCTOR_BIND_MEMBER(&AVRAnalogIn::_timer_event, void)); |
||||
/* Register each private channel with AVRAnalogIn. */ |
||||
_register_channel(&_vcc); |
||||
} |
||||
|
||||
ADCSource* AVRAnalogIn::_create_channel(int16_t chnum) { |
||||
ADCSource *ch = new ADCSource(chnum); |
||||
_register_channel(ch); |
||||
return ch; |
||||
} |
||||
|
||||
void AVRAnalogIn::_register_channel(ADCSource* ch) { |
||||
if (_num_channels >= AVR_INPUT_MAX_CHANNELS) { |
||||
for(;;) { |
||||
hal.console->print_P(PSTR( |
||||
"Error: AP_HAL_AVR::AVRAnalogIn out of channels\r\n")); |
||||
hal.scheduler->delay(1000); |
||||
} |
||||
} |
||||
_channels[_num_channels] = ch; |
||||
/* Need to lock to increment _num_channels as it is used
|
||||
* by the interrupt to access _channels */ |
||||
uint8_t sreg = SREG; |
||||
cli(); |
||||
_num_channels++; |
||||
SREG = sreg; |
||||
|
||||
if (_num_channels == 1) { |
||||
/* After registering the first channel, we can enable the ADC */ |
||||
PRR0 &= ~_BV(PRADC); |
||||
ADCSRA |= _BV(ADEN); |
||||
} |
||||
} |
||||
|
||||
void AVRAnalogIn::_timer_event(void)
|
||||
{ |
||||
if (_channels[_active_channel]->_pin == ANALOG_INPUT_NONE) { |
||||
_channels[_active_channel]->new_sample(0); |
||||
goto next_channel; |
||||
} |
||||
|
||||
if (ADCSRA & _BV(ADSC)) { |
||||
/* ADC Conversion is still running - this should not happen, as we
|
||||
* are called at 1khz. */ |
||||
return; |
||||
} |
||||
|
||||
if (_num_channels == 0) { |
||||
/* No channels are registered - nothing to be done. */ |
||||
return; |
||||
} |
||||
|
||||
_channel_repeat_count++; |
||||
if (_channel_repeat_count < CHANNEL_READ_REPEAT || |
||||
!_channels[_active_channel]->reading_settled()) { |
||||
/* Start a new conversion, throw away the current conversion */ |
||||
ADCSRA |= _BV(ADSC); |
||||
return; |
||||
} |
||||
|
||||
_channel_repeat_count = 0; |
||||
|
||||
/* Read the conversion registers. */ |
||||
{ |
||||
uint8_t low = ADCL; |
||||
uint8_t high = ADCH; |
||||
uint16_t sample = low | (((uint16_t)high) << 8); |
||||
/* Give the active channel a new sample */ |
||||
_channels[_active_channel]->new_sample( sample ); |
||||
} |
||||
next_channel: |
||||
/* stop the previous channel, if a stop pin is defined */ |
||||
_channels[_active_channel]->stop_read(); |
||||
/* Move to the next channel */ |
||||
_active_channel = (_active_channel + 1) % _num_channels; |
||||
/* Setup the next channel's conversion */ |
||||
_channels[_active_channel]->setup_read(); |
||||
/* Start conversion */ |
||||
ADCSRA |= _BV(ADSC); |
||||
} |
||||
|
||||
|
||||
AP_HAL::AnalogSource* AVRAnalogIn::channel(int16_t ch)
|
||||
{ |
||||
if (ch == ANALOG_INPUT_BOARD_VCC) { |
||||
return &_vcc; |
||||
} else { |
||||
return _create_channel(ch); |
||||
} |
||||
} |
||||
|
||||
/*
|
||||
return board voltage in volts |
||||
*/ |
||||
float AVRAnalogIn::board_voltage(void) |
||||
{ |
||||
return _vcc.voltage_latest(); |
||||
} |
||||
|
||||
#endif |
@ -1,222 +0,0 @@
@@ -1,222 +0,0 @@
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#if (CONFIG_HAL_BOARD == HAL_BOARD_APM1 || CONFIG_HAL_BOARD == HAL_BOARD_APM2) |
||||
|
||||
#include <avr/interrupt.h> |
||||
#include <avr/io.h> |
||||
|
||||
#include "utility/pins_arduino_mega.h" |
||||
|
||||
#include "GPIO.h" |
||||
using namespace AP_HAL_AVR; |
||||
|
||||
|
||||
AP_HAL::Proc AVRGPIO::_interrupt_6 = NULL; |
||||
|
||||
SIGNAL(INT6_vect) { |
||||
if (AVRGPIO::_interrupt_6) { |
||||
AVRGPIO::_interrupt_6(); |
||||
} |
||||
}
|
||||
|
||||
// Get the bit location within the hardware port of the given virtual pin.
|
||||
// This comes from the pins_*.c file for the active board configuration.
|
||||
|
||||
#define analogInPinToBit(P) (P) |
||||
|
||||
|
||||
// Get the bit location within the hardware port of the given virtual pin.
|
||||
// This comes from the pins_*.c file for the active board configuration.
|
||||
//
|
||||
// These perform slightly better as macros compared to inline functions
|
||||
//
|
||||
#define digitalPinToPort(P) ( pgm_read_byte( digital_pin_to_port_PGM + (P) ) ) |
||||
#define digitalPinToBitMask(P) ( pgm_read_byte( digital_pin_to_bit_mask_PGM + (P) ) ) |
||||
#define digitalPinToTimer(P) ( pgm_read_byte( digital_pin_to_timer_PGM + (P) ) ) |
||||
#define analogInPinToBit(P) (P) |
||||
#define portOutputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_output_PGM + (P))) ) |
||||
#define portInputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_input_PGM + (P))) ) |
||||
#define portModeRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_mode_PGM + (P))) ) |
||||
|
||||
|
||||
void AVRGPIO::pinMode(uint8_t pin, uint8_t mode) { |
||||
uint8_t bit = digitalPinToBitMask(pin); |
||||
uint8_t port = digitalPinToPort(pin); |
||||
volatile uint8_t *reg; |
||||
|
||||
if (port == NOT_A_PIN) return; |
||||
|
||||
// JWS: can I let the optimizer do this?
|
||||
reg = portModeRegister(port); |
||||
|
||||
if (mode == HAL_GPIO_INPUT) { |
||||
uint8_t oldSREG = SREG; |
||||
cli(); |
||||
*reg &= ~bit; |
||||
SREG = oldSREG; |
||||
} else { |
||||
uint8_t oldSREG = SREG; |
||||
cli(); |
||||
*reg |= bit; |
||||
SREG = oldSREG; |
||||
} |
||||
} |
||||
|
||||
int8_t AVRGPIO::analogPinToDigitalPin(uint8_t pin) |
||||
{ |
||||
return analogInputToDigitalPin(pin); |
||||
} |
||||
|
||||
uint8_t AVRGPIO::read(uint8_t pin) { |
||||
uint8_t bit = digitalPinToBitMask(pin); |
||||
uint8_t port = digitalPinToPort(pin); |
||||
|
||||
if (port == NOT_A_PIN) return 0; |
||||
|
||||
if (*portInputRegister(port) & bit) return 1; |
||||
return 0; |
||||
} |
||||
|
||||
void AVRGPIO::write(uint8_t pin, uint8_t value) { |
||||
uint8_t bit = digitalPinToBitMask(pin); |
||||
uint8_t port = digitalPinToPort(pin); |
||||
volatile uint8_t *out; |
||||
|
||||
if (port == NOT_A_PIN) return; |
||||
|
||||
out = portOutputRegister(port); |
||||
|
||||
uint8_t oldSREG = SREG; |
||||
cli(); |
||||
|
||||
if (value == 0) { |
||||
*out &= ~bit; |
||||
} else { |
||||
*out |= bit; |
||||
} |
||||
|
||||
SREG = oldSREG; |
||||
} |
||||
|
||||
void AVRGPIO::toggle(uint8_t pin) { |
||||
uint8_t bit = digitalPinToBitMask(pin); |
||||
uint8_t port = digitalPinToPort(pin); |
||||
volatile uint8_t *out; |
||||
|
||||
if (port == NOT_A_PIN) return; |
||||
|
||||
out = portOutputRegister(port); |
||||
|
||||
uint8_t oldSREG = SREG; |
||||
cli(); |
||||
|
||||
*out ^= bit; |
||||
|
||||
SREG = oldSREG; |
||||
} |
||||
|
||||
/* Implement GPIO Interrupt 6, used for MPU6000 data ready on APM2. */ |
||||
bool AVRGPIO::attach_interrupt( |
||||
uint8_t interrupt_num, AP_HAL::Proc proc, uint8_t mode) { |
||||
/* Mode is to set the ISCn0 and ISCn1 bits.
|
||||
* These correspond to the GPIO_INTERRUPT_ defs in AP_HAL.h */ |
||||
if (!((mode == HAL_GPIO_INTERRUPT_LOW)|| |
||||
(mode == HAL_GPIO_INTERRUPT_HIGH)|| |
||||
(mode == HAL_GPIO_INTERRUPT_FALLING)|| |
||||
(mode == HAL_GPIO_INTERRUPT_RISING))) return false; |
||||
if (interrupt_num == 6) { |
||||
uint8_t oldSREG = SREG; |
||||
cli();
|
||||
_interrupt_6 = proc; |
||||
/* Set the ISC60 and ICS61 bits in EICRB according to the value
|
||||
* of mode. */ |
||||
EICRB = (EICRB & ~((1 << ISC60) | (1 << ISC61))) | (mode << ISC60); |
||||
EIMSK |= (1 << INT6); |
||||
SREG = oldSREG; |
||||
return true; |
||||
} else { |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
|
||||
AP_HAL::DigitalSource* AVRGPIO::channel(uint16_t pin) { |
||||
uint8_t bit = digitalPinToBitMask(pin); |
||||
uint8_t port = digitalPinToPort(pin); |
||||
if (port == NOT_A_PIN) return NULL; |
||||
return new AVRDigitalSource(bit, port); |
||||
} |
||||
|
||||
void AVRDigitalSource::mode(uint8_t output) { |
||||
const uint8_t bit = _bit; |
||||
const uint8_t port = _port; |
||||
|
||||
volatile uint8_t* reg; |
||||
reg = portModeRegister(port); |
||||
|
||||
if (output == HAL_GPIO_INPUT) { |
||||
uint8_t oldSREG = SREG; |
||||
cli(); |
||||
*reg &= ~bit; |
||||
SREG = oldSREG; |
||||
} else { |
||||
uint8_t oldSREG = SREG; |
||||
cli(); |
||||
*reg |= bit; |
||||
SREG = oldSREG; |
||||
} |
||||
} |
||||
|
||||
uint8_t AVRDigitalSource::read() { |
||||
const uint8_t bit = _bit; |
||||
const uint8_t port = _port; |
||||
if (*portInputRegister(port) & bit) return 1; |
||||
return 0; |
||||
} |
||||
|
||||
void AVRDigitalSource::write(uint8_t value) { |
||||
const uint8_t bit = _bit; |
||||
const uint8_t port = _port; |
||||
volatile uint8_t* out; |
||||
out = portOutputRegister(port); |
||||
|
||||
uint8_t oldSREG = SREG; |
||||
cli(); |
||||
|
||||
if (value == 0) { |
||||
*out &= ~bit; |
||||
} else { |
||||
*out |= bit; |
||||
} |
||||
|
||||
SREG = oldSREG; |
||||
} |
||||
|
||||
void AVRDigitalSource::toggle() { |
||||
const uint8_t bit = _bit; |
||||
const uint8_t port = _port; |
||||
volatile uint8_t* out; |
||||
out = portOutputRegister(port); |
||||
|
||||
uint8_t oldSREG = SREG; |
||||
cli(); |
||||
|
||||
*out ^= bit; |
||||
|
||||
SREG = oldSREG; |
||||
} |
||||
|
||||
/*
|
||||
return true when USB is connected |
||||
*/ |
||||
bool AVRGPIO::usb_connected(void) |
||||
{ |
||||
#if HAL_GPIO_USB_MUX_PIN != -1 |
||||
pinMode(HAL_GPIO_USB_MUX_PIN, HAL_GPIO_INPUT); |
||||
return !read(HAL_GPIO_USB_MUX_PIN); |
||||
#else |
||||
return false; |
||||
#endif |
||||
} |
||||
|
||||
|
||||
#endif |
@ -1,58 +0,0 @@
@@ -1,58 +0,0 @@
|
||||
|
||||
#ifndef __AP_HAL_AVR_GPIO_H__ |
||||
#define __AP_HAL_AVR_GPIO_H__ |
||||
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#include "AP_HAL_AVR_Namespace.h" |
||||
|
||||
#if CONFIG_HAL_BOARD == HAL_BOARD_APM1 |
||||
# define HAL_GPIO_A_LED_PIN 37 |
||||
# define HAL_GPIO_B_LED_PIN 36 |
||||
# define HAL_GPIO_C_LED_PIN 35 |
||||
# define HAL_GPIO_LED_ON HIGH |
||||
# define HAL_GPIO_LED_OFF LOW |
||||
# define HAL_GPIO_USB_MUX_PIN -1 |
||||
#elif CONFIG_HAL_BOARD == HAL_BOARD_APM2 |
||||
# define HAL_GPIO_A_LED_PIN 27 |
||||
# define HAL_GPIO_B_LED_PIN 26 |
||||
# define HAL_GPIO_C_LED_PIN 25 |
||||
# define HAL_GPIO_LED_ON LOW |
||||
# define HAL_GPIO_LED_OFF HIGH |
||||
# define HAL_GPIO_USB_MUX_PIN 23 |
||||
#endif |
||||
|
||||
class AP_HAL_AVR::AVRDigitalSource : public AP_HAL::DigitalSource { |
||||
public: |
||||
AVRDigitalSource(uint8_t bit, uint8_t port) : _bit(bit), _port(port) {} |
||||
void mode(uint8_t output); |
||||
uint8_t read(); |
||||
void write(uint8_t value); |
||||
void toggle(); |
||||
|
||||
private: |
||||
const uint8_t _bit; |
||||
const uint8_t _port; |
||||
}; |
||||
|
||||
class AP_HAL_AVR::AVRGPIO : public AP_HAL::GPIO { |
||||
public: |
||||
AVRGPIO() {} |
||||
void init() {} |
||||
void pinMode(uint8_t pin, uint8_t output); |
||||
int8_t analogPinToDigitalPin(uint8_t pin); |
||||
uint8_t read(uint8_t pin); |
||||
void write(uint8_t pin, uint8_t value); |
||||
void toggle(uint8_t pin); |
||||
AP_HAL::DigitalSource* channel(uint16_t); |
||||
bool attach_interrupt(uint8_t interrupt_num, AP_HAL::Proc proc, |
||||
uint8_t mode); |
||||
|
||||
/* return true if USB cable is connected */ |
||||
bool usb_connected(void); |
||||
|
||||
/* private-ish: only to be used from the appropriate interrupt */ |
||||
static AP_HAL::Proc _interrupt_6; |
||||
}; |
||||
|
||||
#endif // __AP_HAL_AVR_GPIO_H__
|
||||
|
@ -1,105 +0,0 @@
@@ -1,105 +0,0 @@
|
||||
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
|
||||
/* To save linker space, we need to make sure the HAL_AVR_APM1 class
|
||||
* is built iff we are building for HAL_BOARD_APM1. These defines must |
||||
* wrap the whole HAL_AVR_APM1 class declaration and definition. */ |
||||
#if CONFIG_HAL_BOARD == HAL_BOARD_APM1 |
||||
|
||||
#include <assert.h> |
||||
|
||||
#include "AP_HAL_AVR.h" |
||||
#include "AP_HAL_AVR_private.h" |
||||
#include "HAL_AVR_APM1_Class.h" |
||||
|
||||
using namespace AP_HAL; |
||||
using namespace AP_HAL_AVR; |
||||
|
||||
AVRUARTDriverISRs(0); |
||||
AVRUARTDriverISRs(1); |
||||
AVRUARTDriverISRs(3); |
||||
|
||||
AVRUARTDriverInstance(avrUart0Driver, 0); |
||||
AVRUARTDriverInstance(avrUart1Driver, 1); |
||||
AVRUARTDriverInstance(avrUart3Driver, 3); |
||||
|
||||
static AVRSemaphore i2cSemaphore; |
||||
static AVRI2CDriver avrI2CDriver(&i2cSemaphore); |
||||
static APM1SPIDeviceManager apm1SPIDriver; |
||||
static AVRAnalogIn avrAnalogIn; |
||||
static AVREEPROMStorage avrEEPROMStorage; |
||||
static AVRGPIO avrGPIO; |
||||
static APM1RCInput apm1RCInput; |
||||
static APM1RCOutput apm1RCOutput; |
||||
static AVRScheduler avrScheduler; |
||||
static AVRUtil avrUtil; |
||||
|
||||
static ISRRegistry isrRegistry; |
||||
|
||||
/* On APM1 the physical UART2 is used for SPI. */ |
||||
HAL_AVR_APM1::HAL_AVR_APM1() : |
||||
AP_HAL::HAL( |
||||
&avrUart0Driver, /* phys UART0 -> uartA */ |
||||
&avrUart1Driver, /* phys UART1 -> uartB */ |
||||
&avrUart3Driver, /* phys UART3 -> uartC */ |
||||
NULL, /* no uartD */ |
||||
NULL, /* no uartE */ |
||||
&avrI2CDriver, |
||||
NULL, /* only 1 i2c */ |
||||
NULL, /* only 1 i2c */ |
||||
&apm1SPIDriver, |
||||
&avrAnalogIn, |
||||
&avrEEPROMStorage, |
||||
&avrUart0Driver, |
||||
&avrGPIO, |
||||
&apm1RCInput, |
||||
&apm1RCOutput, |
||||
&avrScheduler, |
||||
&avrUtil ) |
||||
{} |
||||
|
||||
void HAL_AVR_APM1::run(int argc, char* const argv[], Callbacks* callbacks) const |
||||
{ |
||||
assert(callbacks); |
||||
|
||||
scheduler->init((void*)&isrRegistry); |
||||
|
||||
/* uartA is the serial port used for the console, so lets make sure
|
||||
* it is initialized at boot */ |
||||
uartA->begin(115200); |
||||
/* The AVR RCInput drivers take an AP_HAL_AVR::ISRRegistry*
|
||||
* as the init argument */ |
||||
rcin->init((void*)&isrRegistry); |
||||
rcout->init(NULL); |
||||
spi->init(NULL); |
||||
i2c->begin(); |
||||
i2c->setTimeout(100); |
||||
analogin->init(NULL); |
||||
|
||||
/* Enable the pullups on the RX pins of the 3 UARTs This is important when
|
||||
* the RX line is high-Z: capacitive coupling between input and output pins |
||||
* can cause bytes written to show up as an input. Occasionally this causes |
||||
* us to detect a phantom GPS by seeing our own outgoing config message. |
||||
* PE0 : RX0 (uartA) |
||||
* PD2 : RX1 (uartB) |
||||
* PJ0 : RX3 (uartC) |
||||
*/ |
||||
|
||||
PORTE |= _BV(0); |
||||
PORTD |= _BV(2); |
||||
PORTJ |= _BV(0); |
||||
|
||||
callbacks->setup(); |
||||
scheduler->system_initialized(); |
||||
|
||||
for (;;) { |
||||
callbacks->loop(); |
||||
} |
||||
} |
||||
|
||||
const AP_HAL::HAL& AP_HAL::get_HAL() { |
||||
static const HAL_AVR_APM1 hal; |
||||
return hal; |
||||
} |
||||
|
||||
#endif // CONFIG_HAL_BOARD == HAL_BOARD_APM1
|
@ -1,33 +0,0 @@
@@ -1,33 +0,0 @@
|
||||
|
||||
#ifndef __AP_HAL_AVR_APM1_HAL_AVR_H__ |
||||
#define __AP_HAL_AVR_APM1_HAL_AVR_H__ |
||||
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
|
||||
/* To save linker space, we need to make sure the HAL_AVR_APM1 class
|
||||
* is built iff we are building for HAL_BOARD_APM1. These defines must |
||||
* wrap the whole HAL_AVR_APM1 class declaration and definition. */ |
||||
#if CONFIG_HAL_BOARD == HAL_BOARD_APM1 |
||||
|
||||
#include "AP_HAL_AVR.h" |
||||
#include "AP_HAL_AVR_Namespace.h" |
||||
|
||||
/**
|
||||
* HAL_AVR_APM1 class derives from HAL but provides a constructor to use the |
||||
* correct drivers for the APM1, and an init to set them all up properly. |
||||
*/ |
||||
|
||||
class HAL_AVR_APM1 : public AP_HAL::HAL { |
||||
public: |
||||
HAL_AVR_APM1(); |
||||
void run(int argc, char* const argv[], Callbacks* callbacks) const override; |
||||
}; |
||||
|
||||
/**
|
||||
* Static instance exported here, defined in the Class.cpp file |
||||
*/ |
||||
extern const HAL_AVR_APM1 AP_HAL_AVR_APM1; |
||||
|
||||
#endif // CONFIG_HAL_BOARD == HAL_BOARD_APM1
|
||||
#endif // __AP_HAL_AVR_APM1_HAL_AVR_H__
|
||||
|
@ -1,104 +0,0 @@
@@ -1,104 +0,0 @@
|
||||
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
|
||||
/* To save linker space, we need to make sure the HAL_AVR_APM2 class
|
||||
* is built iff we are building for HAL_BOARD_APM2. These defines must |
||||
* wrap the whole HAL_AVR_APM2 class declaration and definition. */ |
||||
#if CONFIG_HAL_BOARD == HAL_BOARD_APM2 |
||||
|
||||
#include <assert.h> |
||||
|
||||
#include "AP_HAL_AVR.h" |
||||
#include "AP_HAL_AVR_private.h" |
||||
#include "HAL_AVR_APM2_Class.h" |
||||
|
||||
using namespace AP_HAL; |
||||
using namespace AP_HAL_AVR; |
||||
|
||||
AVRUARTDriverISRs(0); |
||||
AVRUARTDriverISRs(1); |
||||
AVRUARTDriverISRs(2); |
||||
|
||||
AVRUARTDriverInstance(avrUart0Driver, 0); |
||||
AVRUARTDriverInstance(avrUart1Driver, 1); |
||||
AVRUARTDriverInstance(avrUart2Driver, 2); |
||||
|
||||
static AVRSemaphore i2cSemaphore; |
||||
static AVRI2CDriver avrI2CDriver(&i2cSemaphore); |
||||
static APM2SPIDeviceManager apm2SPIDriver; |
||||
static AVRAnalogIn avrAnalogIn; |
||||
static AVREEPROMStorage avrEEPROMStorage; |
||||
static AVRGPIO avrGPIO; |
||||
static APM2RCInput apm2RCInput; |
||||
static APM2RCOutput apm2RCOutput; |
||||
static AVRScheduler avrScheduler; |
||||
static AVRUtil avrUtil; |
||||
|
||||
static ISRRegistry isrRegistry; |
||||
|
||||
HAL_AVR_APM2::HAL_AVR_APM2() : |
||||
AP_HAL::HAL( |
||||
&avrUart0Driver, /* phys UART0 -> uartA */ |
||||
&avrUart1Driver, /* phys UART1 -> uartB */ |
||||
&avrUart2Driver, /* phys UART2 -> uartC */ |
||||
NULL, /* no uartD */ |
||||
NULL, /* no uartE */ |
||||
&avrI2CDriver, |
||||
NULL, /* only one i2c */ |
||||
NULL, /* only one i2c */ |
||||
&apm2SPIDriver, |
||||
&avrAnalogIn, |
||||
&avrEEPROMStorage, |
||||
&avrUart0Driver, |
||||
&avrGPIO, |
||||
&apm2RCInput, |
||||
&apm2RCOutput, |
||||
&avrScheduler, |
||||
&avrUtil ) |
||||
{} |
||||
|
||||
void HAL_AVR_APM2::run(int argc, char* const argv[], Callbacks* callbacks) const |
||||
{ |
||||
assert(callbacks); |
||||
|
||||
scheduler->init((void*)&isrRegistry); |
||||
|
||||
/* uartA is the serial port used for the console, so lets make sure
|
||||
* it is initialized at boot */ |
||||
uartA->begin(115200, 128, 128); |
||||
/* The AVR RCInput drivers take an AP_HAL_AVR::ISRRegistry*
|
||||
* as the init argument */ |
||||
rcin->init((void*)&isrRegistry); |
||||
rcout->init(NULL); |
||||
spi->init(NULL); |
||||
i2c->begin(); |
||||
i2c->setTimeout(100); |
||||
analogin->init(NULL); |
||||
|
||||
/* Enable the pullups on the RX pins of the 3 UARTs This is important when
|
||||
* the RX line is high-Z: capacitive coupling between input and output pins |
||||
* can cause bytes written to show up as an input. Occasionally this causes |
||||
* us to detect a phantom GPS by seeing our own outgoing config message. |
||||
* PE0 : RX0 (uartA) |
||||
* PD2 : RX1 (uartB) |
||||
* PH0 : RX2 (uartC) |
||||
*/ |
||||
|
||||
PORTE |= _BV(0); |
||||
PORTD |= _BV(2); |
||||
PORTH |= _BV(0); |
||||
|
||||
callbacks->setup(); |
||||
scheduler->system_initialized(); |
||||
|
||||
for (;;) { |
||||
callbacks->loop(); |
||||
} |
||||
} |
||||
|
||||
const AP_HAL::HAL& AP_HAL::get_HAL() { |
||||
static const HAL_AVR_APM2 hal; |
||||
return hal; |
||||
} |
||||
|
||||
#endif // CONFIG_HAL_BOARD == HAL_BOARD_APM2
|
@ -1,33 +0,0 @@
@@ -1,33 +0,0 @@
|
||||
|
||||
#ifndef __AP_HAL_AVR_APM2_HAL_AVR_H__ |
||||
#define __AP_HAL_AVR_APM2_HAL_AVR_H__ |
||||
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
|
||||
/* To save linker space, we need to make sure the HAL_AVR_APM2 class
|
||||
* is built iff we are building for HAL_BOARD_APM2. These defines must |
||||
* wrap the whole HAL_AVR_APM2 class declaration and definition. */ |
||||
#if CONFIG_HAL_BOARD == HAL_BOARD_APM2 |
||||
|
||||
#include "AP_HAL_AVR.h" |
||||
#include "AP_HAL_AVR_Namespace.h" |
||||
|
||||
/**
|
||||
* HAL_AVR_APM2 class derives from HAL but provides an AVR-specific |
||||
* init method. |
||||
*/ |
||||
|
||||
class HAL_AVR_APM2 : public AP_HAL::HAL { |
||||
public: |
||||
HAL_AVR_APM2(); |
||||
void run(int argc, char* const argv[], Callbacks* callbacks) const override; |
||||
}; |
||||
|
||||
/**
|
||||
* Static instance exported here, defined in the Class.cpp file |
||||
*/ |
||||
extern const HAL_AVR_APM2 AP_HAL_AVR_APM2; |
||||
|
||||
#endif // CONFIG_HAL_BOARD == HAL_BOARD_APM2
|
||||
#endif // __AP_HAL_AVR_APM2_HAL_AVR_H__
|
||||
|
@ -1,323 +0,0 @@
@@ -1,323 +0,0 @@
|
||||
/*
|
||||
This program is free software: you can redistribute it and/or modify |
||||
it under the terms of the GNU General Public License as published by |
||||
the Free Software Foundation, either version 3 of the License, or |
||||
(at your option) any later version. |
||||
|
||||
This program is distributed in the hope that it will be useful, |
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
GNU General Public License for more details. |
||||
|
||||
You should have received a copy of the GNU General Public License |
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
|
||||
/*
|
||||
* AP_HAL_AVR I2C driver. derived from: |
||||
* I2C.cpp - I2C library |
||||
* Copyright (c) 2011 Wayne Truchsess. All right reserved. |
||||
* Rev 2.0 - September 19th, 2011 |
||||
* - Added support for timeout function to prevent |
||||
* and recover from bus lockup (thanks to PaulS |
||||
* and CrossRoads on the Arduino forum) |
||||
* - Changed return type for stop() from void to |
||||
* uint8_t to handle timeOut function |
||||
* Rev 1.0 - August 8th, 2011 |
||||
* |
||||
* This is a modified version of the Arduino Wire/TWI |
||||
* library. Functions were rewritten to provide more functionality |
||||
* and also the use of Repeated Start. Some I2C devices will not |
||||
* function correctly without the use of a Repeated Start. The |
||||
* initial version of this library only supports the Master. |
||||
* |
||||
*/ |
||||
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#if (CONFIG_HAL_BOARD == HAL_BOARD_APM1 || CONFIG_HAL_BOARD == HAL_BOARD_APM2) |
||||
|
||||
#include <inttypes.h> |
||||
|
||||
#include <avr/io.h> |
||||
#include <avr/interrupt.h> |
||||
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#include "I2CDriver.h" |
||||
using namespace AP_HAL_AVR; |
||||
|
||||
extern const AP_HAL::HAL& hal; |
||||
|
||||
#ifndef F_CPU |
||||
#define CPU_FREQ 16000000L |
||||
#else |
||||
#define CPU_FREQ F_CPU |
||||
#endif |
||||
|
||||
#define START 0x08 |
||||
#define REPEATED_START 0x10 |
||||
#define MT_SLA_ACK 0x18 |
||||
#define MT_DATA_ACK 0x28 |
||||
#define MR_SLA_ACK 0x40 |
||||
#define MR_DATA_ACK 0x50 |
||||
#define MR_DATA_NACK 0x58 |
||||
#define TWI_STATUS (TWSR & 0xF8) |
||||
|
||||
#define SLA_W(address) (address << 1) |
||||
#define SLA_R(address) ((address << 1) + 0x01) |
||||
|
||||
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) |
||||
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) |
||||
|
||||
void AVRI2CDriver::begin() { |
||||
// activate internal pull-ups for twi
|
||||
// as per note from atmega128 manual pg204
|
||||
sbi(PORTD, 0); |
||||
sbi(PORTD, 1); |
||||
|
||||
// initialize twi prescaler and bit rate
|
||||
cbi(TWSR, TWPS0); |
||||
cbi(TWSR, TWPS1); |
||||
|
||||
// start in high speed. When a driver gets an error it drops it to
|
||||
// low speed
|
||||
setHighSpeed(true); |
||||
|
||||
// enable twi module, acks, and twi interrupt
|
||||
TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA); |
||||
} |
||||
|
||||
void AVRI2CDriver::end() { |
||||
TWCR = 0; |
||||
} |
||||
|
||||
void AVRI2CDriver::setHighSpeed(bool active) { |
||||
if (active) { |
||||
TWBR = ((CPU_FREQ / 400000) - 16) / 2; |
||||
} else { |
||||
TWBR = ((CPU_FREQ / 100000) - 16) / 2; |
||||
} |
||||
} |
||||
|
||||
uint8_t AVRI2CDriver::write(uint8_t addr, uint8_t len, uint8_t* data){ |
||||
uint8_t stat = _start(); |
||||
if (stat) goto error; |
||||
stat = _sendAddress(SLA_W(addr)); |
||||
if (stat) goto error; |
||||
for (uint8_t i = 0; i < len; i++) |
||||
{ |
||||
stat = _sendByte(data[i]); |
||||
if (stat) goto error; |
||||
} |
||||
stat = _stop(); |
||||
if (stat) goto error; |
||||
return stat; |
||||
error: |
||||
_lockup_count++; |
||||
return stat; |
||||
} |
||||
|
||||
uint8_t AVRI2CDriver::writeRegisters(uint8_t addr, uint8_t reg, |
||||
uint8_t len, uint8_t* data){ |
||||
uint8_t stat = _start(); |
||||
if (stat) goto error; |
||||
stat = _sendAddress(SLA_W(addr)); |
||||
if (stat) goto error; |
||||
stat = _sendByte(reg); |
||||
if (stat) goto error; |
||||
for (uint8_t i = 0; i < len; i++) |
||||
{ |
||||
stat = _sendByte(data[i]); |
||||
if (stat) goto error; |
||||
} |
||||
stat = _stop(); |
||||
if (stat) goto error; |
||||
return stat; |
||||
error: |
||||
if (!_ignore_errors) { |
||||
_lockup_count++; |
||||
} |
||||
return stat; |
||||
} |
||||
|
||||
uint8_t AVRI2CDriver::writeRegister(uint8_t addr, uint8_t reg, uint8_t val) { |
||||
/* Sometimes avr-gcc fails at dereferencing a uint8_t arg. */ |
||||
uint8_t data[1]; |
||||
data[0] = val; |
||||
return writeRegisters(addr, reg, 1, data); |
||||
} |
||||
|
||||
uint8_t AVRI2CDriver::read(uint8_t addr, uint8_t len, uint8_t* data){ |
||||
uint8_t stat; |
||||
if ( len == 0) |
||||
len = 1; |
||||
uint8_t nackposition = len - 1; |
||||
stat = 0; |
||||
stat = _start(); |
||||
if(stat) goto error; |
||||
stat = _sendAddress(SLA_R(addr)); |
||||
if(stat) goto error; |
||||
for(uint8_t i = 0; i < len ; i++) { |
||||
if ( i == nackposition ) { |
||||
stat = _receiveByte(false); |
||||
if (stat != MR_DATA_NACK) goto error; |
||||
} else { |
||||
stat = _receiveByte(true); |
||||
if (stat != MR_DATA_ACK) goto error; |
||||
} |
||||
data[i] = TWDR; |
||||
} |
||||
stat = _stop(); |
||||
if (stat) goto error; |
||||
return stat; |
||||
error: |
||||
_lockup_count++; |
||||
return stat; |
||||
} |
||||
|
||||
uint8_t AVRI2CDriver::readRegisters(uint8_t addr, uint8_t reg, |
||||
uint8_t len, uint8_t* data){ |
||||
uint8_t stat; |
||||
if ( len == 0) |
||||
len = 1; |
||||
uint8_t nackposition = len - 1; |
||||
stat = 0; |
||||
stat = _start(); |
||||
if(stat) goto error; |
||||
stat = _sendAddress(SLA_W(addr)); |
||||
if(stat) goto error; |
||||
stat = _sendByte(reg); |
||||
if(stat) goto error; |
||||
stat = _start(); |
||||
if(stat) goto error; |
||||
stat = _sendAddress(SLA_R(addr)); |
||||
if(stat) goto error; |
||||
for(uint8_t i = 0; i < len ; i++) { |
||||
if ( i == nackposition ) { |
||||
stat = _receiveByte(false); |
||||
if (stat != MR_DATA_NACK) goto error; |
||||
} else { |
||||
stat = _receiveByte(true); |
||||
if (stat != MR_DATA_ACK) goto error; |
||||
} |
||||
data[i] = TWDR; |
||||
} |
||||
stat = _stop(); |
||||
if (stat) goto error; |
||||
return stat; |
||||
error: |
||||
_lockup_count++; |
||||
return stat; |
||||
} |
||||
|
||||
uint8_t AVRI2CDriver::readRegister(uint8_t addr, uint8_t reg, uint8_t* data) { |
||||
return readRegisters(addr, reg, 1, data); |
||||
} |
||||
|
||||
uint8_t AVRI2CDriver::_start() { |
||||
TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN); |
||||
uint8_t stat = _waitInterrupt(); |
||||
if (stat) return stat; |
||||
|
||||
if ((TWI_STATUS == START) || (TWI_STATUS == REPEATED_START)) { |
||||
return 0; |
||||
} else { |
||||
return TWI_STATUS; |
||||
} |
||||
} |
||||
|
||||
uint8_t AVRI2CDriver::_stop() { |
||||
TWCR = _BV(TWINT) | _BV(TWEN) | _BV(TWSTO); |
||||
return _waitStop(); |
||||
} |
||||
|
||||
uint8_t AVRI2CDriver::_sendAddress(uint8_t addr) { |
||||
TWDR = addr; |
||||
TWCR = _BV(TWINT) | _BV(TWEN); |
||||
return _waitInterrupt(); |
||||
} |
||||
|
||||
uint8_t AVRI2CDriver::_sendByte(uint8_t data) { |
||||
TWDR = data; |
||||
TWCR = _BV(TWINT) | _BV(TWEN); |
||||
uint8_t stat = _waitInterrupt(); |
||||
if (stat) return stat; |
||||
|
||||
if (TWI_STATUS == MT_DATA_ACK) { |
||||
return 0; |
||||
} else { |
||||
return TWI_STATUS; |
||||
} |
||||
} |
||||
|
||||
uint8_t AVRI2CDriver::_receiveByte(bool ack) { |
||||
if (ack) { |
||||
TWCR = _BV(TWINT) | _BV(TWEN) | _BV(TWEA); |
||||
} else { |
||||
TWCR = _BV(TWINT) | _BV(TWEN); |
||||
} |
||||
uint8_t stat = _waitInterrupt(); |
||||
if (stat) return stat; |
||||
return TWI_STATUS; |
||||
} |
||||
|
||||
void AVRI2CDriver::_handleLockup() { |
||||
TWCR = 0; /* Releases SDA and SCL lines to high impedance */ |
||||
TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA); /* Reinitialize TWI */ |
||||
_lockup_count++; |
||||
} |
||||
|
||||
uint8_t AVRI2CDriver::_waitInterrupt() { |
||||
uint32_t start = hal.scheduler->millis(); |
||||
if (_timeoutDelay == 0) { |
||||
/* Wait indefinitely for interrupt to go off */ |
||||
while (!(TWCR & _BV(TWINT))) { } |
||||
} else { |
||||
/* Wait while polling for timeout */ |
||||
while (!(TWCR & _BV(TWINT))) { |
||||
uint32_t current = hal.scheduler->millis(); |
||||
if ( current - start >= _timeoutDelay ) { |
||||
_handleLockup(); |
||||
return 1; |
||||
} |
||||
} |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
uint8_t AVRI2CDriver::_waitStop() { |
||||
uint32_t start = hal.scheduler->millis(); |
||||
if (_timeoutDelay == 0) { |
||||
/* Wait indefinitely for stop condition */ |
||||
while( TWCR & _BV(TWSTO) ) { } |
||||
} else { |
||||
/* Wait while polling for timeout */ |
||||
while( TWCR & _BV(TWSTO) ) { |
||||
uint32_t current = hal.scheduler->millis(); |
||||
if (current - start >= _timeoutDelay) { |
||||
_handleLockup();
|
||||
return 1; |
||||
} |
||||
} |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
SIGNAL(TWI_vect) |
||||
{ |
||||
switch(TWI_STATUS) { |
||||
case 0x20: |
||||
case 0x30: |
||||
case 0x48: |
||||
TWCR = _BV(TWINT) | _BV(TWEN) | _BV(TWSTO); // send a stop
|
||||
break; |
||||
case 0x38: |
||||
case 0x68: |
||||
case 0x78: |
||||
case 0xB0: |
||||
TWCR = 0; //releases SDA and SCL lines to high impedance
|
||||
TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA); //reinitialize TWI
|
||||
break; |
||||
} |
||||
} |
||||
|
||||
#endif |
@ -1,49 +0,0 @@
@@ -1,49 +0,0 @@
|
||||
|
||||
#ifndef __AP_HAL_AVR_I2C_DRIVER_H__ |
||||
#define __AP_HAL_AVR_I2C_DRIVER_H__ |
||||
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#include "AP_HAL_AVR_Namespace.h" |
||||
|
||||
#define AVRI2CDRIVER_MAX_BUFFER_SIZE 32 |
||||
|
||||
class AP_HAL_AVR::AVRI2CDriver : public AP_HAL::I2CDriver { |
||||
public: |
||||
AVRI2CDriver(AP_HAL::Semaphore *sem) : _sem(sem) {} |
||||
|
||||
void begin(); |
||||
void end(); |
||||
void setTimeout(uint16_t ms) { _timeoutDelay = ms; } |
||||
void setHighSpeed(bool active); |
||||
|
||||
uint8_t write(uint8_t addr, uint8_t len, uint8_t* data); |
||||
uint8_t writeRegister(uint8_t addr, uint8_t reg, uint8_t val); |
||||
uint8_t writeRegisters(uint8_t addr, uint8_t reg, |
||||
uint8_t len, uint8_t* data); |
||||
uint8_t read(uint8_t addr, uint8_t len, uint8_t* data); |
||||
uint8_t readRegister(uint8_t addr, uint8_t reg, uint8_t* data); |
||||
uint8_t readRegisters(uint8_t addr, uint8_t reg, |
||||
uint8_t len, uint8_t* data); |
||||
uint8_t lockup_count() { return _lockup_count; } |
||||
|
||||
AP_HAL::Semaphore* get_semaphore() { return _sem; } |
||||
|
||||
private: |
||||
uint8_t _start(); |
||||
uint8_t _stop(); |
||||
uint8_t _sendAddress(uint8_t addr); |
||||
uint8_t _sendByte(uint8_t data); |
||||
uint8_t _receiveByte(bool ack); |
||||
void _handleLockup(); |
||||
|
||||
uint8_t _waitInterrupt(); |
||||
uint8_t _waitStop(); |
||||
|
||||
uint8_t _lockup_count; |
||||
uint16_t _timeoutDelay; |
||||
|
||||
AP_HAL::Semaphore *_sem; |
||||
}; |
||||
|
||||
#endif // __AP_HAL_AVR_I2C_DRIVER_H__
|
||||
|
@ -1,103 +0,0 @@
@@ -1,103 +0,0 @@
|
||||
|
||||
#ifndef __AP_HAL_AVR_RC_INPUT_H__ |
||||
#define __AP_HAL_AVR_RC_INPUT_H__ |
||||
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#include "AP_HAL_AVR_Namespace.h" |
||||
|
||||
#define AVR_RC_INPUT_NUM_CHANNELS 11 |
||||
#define AVR_RC_INPUT_MIN_CHANNELS 5 // for ppm sum we allow less than 8 channels to make up a valid packet
|
||||
|
||||
/*
|
||||
mininum pulse width in microseconds to signal end of a PPM-SUM |
||||
frame. This value is chosen to be smaller than the default 3000 sync |
||||
pulse width for OpenLRSng. Note that this is the total pulse with |
||||
(typically 300us low followed by a long high pulse) |
||||
*/ |
||||
#define AVR_RC_INPUT_MIN_SYNC_PULSE_WIDTH 2700 |
||||
|
||||
class AP_HAL_AVR::APM1RCInput : public AP_HAL::RCInput { |
||||
public: |
||||
/**
|
||||
* init: |
||||
* HAL_AVR::init should pass in a AP_HAL_AVR::ISRRegistry* as a void* |
||||
*/ |
||||
void init(void* isrregistry); |
||||
|
||||
/**
|
||||
* Return true if there has been new input since the last read() |
||||
* call. This call also clears the new_input flag, so once it |
||||
* returns true it won't return true again until another frame is |
||||
* received. |
||||
*/ |
||||
bool new_input(); |
||||
|
||||
/**
|
||||
* Return the number of input channels in last read() |
||||
*/ |
||||
uint8_t num_channels(); |
||||
|
||||
/**
|
||||
* read(uint8_t): |
||||
* Read a single channel at a time |
||||
*/ |
||||
uint16_t read(uint8_t ch); |
||||
|
||||
/**
|
||||
* read(uint16_t*,uint8_t): |
||||
* Read an array of channels, return the valid count |
||||
*/ |
||||
uint8_t read(uint16_t* periods, uint8_t len); |
||||
|
||||
/**
|
||||
* Overrides: these are really grody and don't belong here but we need |
||||
* them at the moment to make the port work. |
||||
* case v of: |
||||
* v == -1 -> no change to this channel |
||||
* v == 0 -> do not override this channel |
||||
* v > 0 -> set v as override. |
||||
*/ |
||||
|
||||
/* set_overrides: array starts at ch 0, for len channels */ |
||||
bool set_overrides(int16_t *overrides, uint8_t len); |
||||
/* set_override: set just a specific channel */ |
||||
bool set_override(uint8_t channel, int16_t override); |
||||
/* clear_overrides: equivelant to setting all overrides to 0 */ |
||||
void clear_overrides(); |
||||
|
||||
private: |
||||
/* private callback for input capture ISR */ |
||||
static void _timer4_capt_cb(void); |
||||
/* private variables to communicate with input capture isr */ |
||||
static volatile uint16_t _pulse_capt[AVR_RC_INPUT_NUM_CHANNELS]; |
||||
static volatile uint8_t _num_channels; |
||||
static volatile bool _new_input; |
||||
|
||||
/* override state */ |
||||
uint16_t _override[AVR_RC_INPUT_NUM_CHANNELS];
|
||||
}; |
||||
|
||||
class AP_HAL_AVR::APM2RCInput : public AP_HAL::RCInput { |
||||
/* Pass in a AP_HAL_AVR::ISRRegistry* as void*. */ |
||||
void init(void* isrregistry); |
||||
bool new_input(); |
||||
uint8_t num_channels(); |
||||
uint16_t read(uint8_t ch); |
||||
uint8_t read(uint16_t* periods, uint8_t len); |
||||
bool set_overrides(int16_t *overrides, uint8_t len); |
||||
bool set_override(uint8_t channel, int16_t override); |
||||
void clear_overrides(); |
||||
private: |
||||
/* private callback for input capture ISR */ |
||||
static void _timer5_capt_cb(void); |
||||
/* private variables to communicate with input capture isr */ |
||||
static volatile uint16_t _pulse_capt[AVR_RC_INPUT_NUM_CHANNELS]; |
||||
static volatile uint8_t _num_channels; |
||||
static volatile bool _new_input; |
||||
|
||||
/* override state */ |
||||
uint16_t _override[AVR_RC_INPUT_NUM_CHANNELS];
|
||||
}; |
||||
|
||||
#endif // __AP_HAL_AVR_RC_INPUT_H__
|
||||
|
@ -1,177 +0,0 @@
@@ -1,177 +0,0 @@
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#if (CONFIG_HAL_BOARD == HAL_BOARD_APM1 || CONFIG_HAL_BOARD == HAL_BOARD_APM2) |
||||
|
||||
#include <avr/io.h> |
||||
#include <avr/interrupt.h> |
||||
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#include "AP_HAL_AVR.h" |
||||
#include "RCInput.h" |
||||
#include "utility/ISRRegistry.h" |
||||
using namespace AP_HAL; |
||||
using namespace AP_HAL_AVR; |
||||
|
||||
extern const HAL& hal; |
||||
|
||||
/* private variables to communicate with input capture isr */ |
||||
volatile uint16_t APM1RCInput::_pulse_capt[AVR_RC_INPUT_NUM_CHANNELS] = {0};
|
||||
volatile uint8_t APM1RCInput::_num_channels = 0; |
||||
volatile bool APM1RCInput::_new_input = false; |
||||
|
||||
/* private callback for input capture ISR */ |
||||
void APM1RCInput::_timer4_capt_cb(void) { |
||||
static uint16_t icr4_prev; |
||||
static uint8_t channel_ctr; |
||||
|
||||
const uint16_t icr4_current = ICR4; |
||||
uint16_t pulse_width; |
||||
if (icr4_current < icr4_prev) { |
||||
/* ICR4 rolls over at TOP=40000 */ |
||||
pulse_width = icr4_current + 40000 - icr4_prev; |
||||
} else { |
||||
pulse_width = icr4_current - icr4_prev; |
||||
} |
||||
|
||||
if (pulse_width > AVR_RC_INPUT_MIN_SYNC_PULSE_WIDTH*2) { |
||||
// sync pulse detected. Pass through values if at least a minimum number of channels received
|
||||
if( channel_ctr >= AVR_RC_INPUT_MIN_CHANNELS ) { |
||||
_num_channels = channel_ctr; |
||||
_new_input = true; |
||||
} |
||||
channel_ctr = 0; |
||||
} else { |
||||
if (channel_ctr < AVR_RC_INPUT_NUM_CHANNELS) { |
||||
_pulse_capt[channel_ctr] = pulse_width; |
||||
channel_ctr++; |
||||
if (channel_ctr == AVR_RC_INPUT_NUM_CHANNELS) { |
||||
_num_channels = AVR_RC_INPUT_NUM_CHANNELS; |
||||
_new_input = true; |
||||
} |
||||
} |
||||
} |
||||
icr4_prev = icr4_current; |
||||
} |
||||
|
||||
void APM1RCInput::init(void* _isrregistry) { |
||||
ISRRegistry* isrregistry = (ISRRegistry*) _isrregistry; |
||||
isrregistry->register_signal(ISR_REGISTRY_TIMER4_CAPT, _timer4_capt_cb); |
||||
|
||||
/* initialize overrides */ |
||||
clear_overrides(); |
||||
/* Arduino pin 49 is ICP4 / PL0, timer 4 input capture */ |
||||
hal.gpio->pinMode(49, HAL_GPIO_INPUT); |
||||
/**
|
||||
* WGM: 1 1 1 1. Fast WPM, TOP is in OCR4A |
||||
* COM all disabled |
||||
* CS41: prescale by 8 => 0.5us tick |
||||
* ICES4: input capture on rising edge |
||||
* OCR4A: 40000, 0.5us tick => 2ms period / 50hz freq for outbound |
||||
* fast PWM. |
||||
*/ |
||||
|
||||
uint8_t oldSREG = SREG; |
||||
cli(); |
||||
|
||||
/* Timer cleanup before configuring */ |
||||
TCNT4 = 0; |
||||
TIFR4 = 0; |
||||
|
||||
/* Set timer 8x prescaler fast PWM mode toggle compare at OCRA with rising edge input capture */ |
||||
TCCR4A = _BV(WGM40) | _BV(WGM41); |
||||
TCCR4B |= _BV(WGM43) | _BV(WGM42) | _BV(CS41) | _BV(ICES4); |
||||
OCR4A = 40000 - 1; // -1 to correct for wrap
|
||||
|
||||
/* OCR4B and OCR4C will be used by RCOutput_APM1. Init to 0xFFFF to prevent premature PWM output */ |
||||
OCR4B = 0xFFFF; |
||||
OCR4C = 0xFFFF; |
||||
|
||||
/* Enable input capture interrupt */ |
||||
TIMSK4 |= _BV(ICIE4); |
||||
|
||||
SREG = oldSREG;
|
||||
} |
||||
|
||||
bool APM1RCInput::new_input()
|
||||
{
|
||||
if (_new_input) { |
||||
_new_input = false; |
||||
return true; |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
uint8_t APM1RCInput::num_channels() { return _num_channels; } |
||||
|
||||
|
||||
/* constrain captured pulse to be between min and max pulsewidth. */ |
||||
static inline uint16_t constrain_pulse(uint16_t p) { |
||||
if (p > RC_INPUT_MAX_PULSEWIDTH) return RC_INPUT_MAX_PULSEWIDTH; |
||||
if (p < RC_INPUT_MIN_PULSEWIDTH) return RC_INPUT_MIN_PULSEWIDTH; |
||||
return p; |
||||
} |
||||
|
||||
uint16_t APM1RCInput::read(uint8_t ch) { |
||||
/* constrain ch */ |
||||
if (ch >= AVR_RC_INPUT_NUM_CHANNELS) return 0; |
||||
/* grab channel from isr's memory in critical section*/ |
||||
uint8_t oldSREG = SREG; |
||||
cli(); |
||||
uint16_t capt = _pulse_capt[ch]; |
||||
SREG = oldSREG; |
||||
/* scale _pulse_capt from 0.5us units to 1us units. */ |
||||
uint16_t pulse = constrain_pulse(capt >> 1); |
||||
/* Check for override */ |
||||
uint16_t over = _override[ch]; |
||||
return (over == 0) ? pulse : over; |
||||
} |
||||
|
||||
uint8_t APM1RCInput::read(uint16_t* periods, uint8_t len) { |
||||
/* constrain len */ |
||||
if (len > AVR_RC_INPUT_NUM_CHANNELS) { len = AVR_RC_INPUT_NUM_CHANNELS; } |
||||
/* grab channels from isr's memory in critical section */ |
||||
uint8_t oldSREG = SREG; |
||||
cli(); |
||||
for (uint8_t i = 0; i < len; i++) { |
||||
periods[i] = _pulse_capt[i]; |
||||
} |
||||
SREG = oldSREG; |
||||
/* Outside of critical section, do the math (in place) to scale and
|
||||
* constrain the pulse. */ |
||||
for (uint8_t i = 0; i < len; i++) { |
||||
/* scale _pulse_capt from 0.5us units to 1us units. */ |
||||
periods[i] = constrain_pulse(periods[i] >> 1); |
||||
/* check for override */ |
||||
if (_override[i] != 0) { |
||||
periods[i] = _override[i]; |
||||
} |
||||
} |
||||
return _num_channels; |
||||
} |
||||
|
||||
bool APM1RCInput::set_overrides(int16_t *overrides, uint8_t len) { |
||||
bool res = false; |
||||
for (uint8_t i = 0; i < len; i++) { |
||||
res |= set_override(i, overrides[i]); |
||||
} |
||||
return res; |
||||
} |
||||
|
||||
bool APM1RCInput::set_override(uint8_t channel, int16_t override) { |
||||
if (override < 0) return false; /* -1: no change. */ |
||||
if (channel < AVR_RC_INPUT_NUM_CHANNELS) { |
||||
_override[channel] = override; |
||||
if (override != 0) { |
||||
_new_input = true; |
||||
return true; |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
void APM1RCInput::clear_overrides() { |
||||
for (uint8_t i = 0; i < AVR_RC_INPUT_NUM_CHANNELS; i++) { |
||||
_override[i] = 0; |
||||
} |
||||
} |
||||
|
||||
#endif |
@ -1,177 +0,0 @@
@@ -1,177 +0,0 @@
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#if (CONFIG_HAL_BOARD == HAL_BOARD_APM1 || CONFIG_HAL_BOARD == HAL_BOARD_APM2) |
||||
|
||||
#include <avr/io.h> |
||||
#include <avr/interrupt.h> |
||||
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#include "AP_HAL_AVR.h" |
||||
#include "RCInput.h" |
||||
#include "utility/ISRRegistry.h" |
||||
using namespace AP_HAL; |
||||
using namespace AP_HAL_AVR; |
||||
|
||||
extern const HAL& hal; |
||||
|
||||
/* private variables to communicate with input capture isr */ |
||||
volatile uint16_t APM2RCInput::_pulse_capt[AVR_RC_INPUT_NUM_CHANNELS] = {0};
|
||||
volatile uint8_t APM2RCInput::_num_channels = 0; |
||||
volatile bool APM2RCInput::_new_input = false; |
||||
|
||||
/* private callback for input capture ISR */ |
||||
void APM2RCInput::_timer5_capt_cb(void) { |
||||
static uint16_t icr5_prev; |
||||
static uint8_t channel_ctr; |
||||
|
||||
const uint16_t icr5_current = ICR5; |
||||
uint16_t pulse_width; |
||||
if (icr5_current < icr5_prev) { |
||||
/* ICR5 rolls over at TOP=40000 */ |
||||
pulse_width = icr5_current + 40000 - icr5_prev; |
||||
} else { |
||||
pulse_width = icr5_current - icr5_prev; |
||||
} |
||||
|
||||
if (pulse_width > AVR_RC_INPUT_MIN_SYNC_PULSE_WIDTH*2) { |
||||
// sync pulse detected. Pass through values if at least a minimum number of channels received
|
||||
if( channel_ctr >= AVR_RC_INPUT_MIN_CHANNELS ) { |
||||
_num_channels = channel_ctr; |
||||
_new_input = true; |
||||
} |
||||
channel_ctr = 0; |
||||
} else { |
||||
if (channel_ctr < AVR_RC_INPUT_NUM_CHANNELS) { |
||||
_pulse_capt[channel_ctr] = pulse_width; |
||||
channel_ctr++; |
||||
if (channel_ctr == AVR_RC_INPUT_NUM_CHANNELS) { |
||||
_num_channels = AVR_RC_INPUT_NUM_CHANNELS; |
||||
_new_input = true; |
||||
} |
||||
} |
||||
} |
||||
icr5_prev = icr5_current; |
||||
} |
||||
|
||||
void APM2RCInput::init(void* _isrregistry) { |
||||
ISRRegistry* isrregistry = (ISRRegistry*) _isrregistry; |
||||
isrregistry->register_signal(ISR_REGISTRY_TIMER5_CAPT, _timer5_capt_cb); |
||||
|
||||
/* initialize overrides */ |
||||
clear_overrides(); |
||||
/* Arduino pin 48 is ICP5 / PL1, timer 5 input capture */ |
||||
hal.gpio->pinMode(48, HAL_GPIO_INPUT); |
||||
/**
|
||||
* WGM: 1 1 1 1. Fast WPM, TOP is in OCR5A |
||||
* COM all disabled |
||||
* CS51: prescale by 8 => 0.5us tick |
||||
* ICES5: input capture on rising edge |
||||
* OCR5A: 40000, 0.5us tick => 2ms period / 50hz freq for outbound |
||||
* fast PWM. |
||||
*/ |
||||
|
||||
uint8_t oldSREG = SREG; |
||||
cli(); |
||||
|
||||
/* Timer cleanup before configuring */ |
||||
TCNT5 = 0; |
||||
TIFR5 = 0; |
||||
|
||||
/* Set timer 8x prescaler fast PWM mode toggle compare at OCRA with rising edge input capture */ |
||||
TCCR5A = _BV(WGM50) | _BV(WGM51); |
||||
TCCR5B |= _BV(WGM53) | _BV(WGM52) | _BV(CS51) | _BV(ICES5); |
||||
OCR5A = 40000 - 1; // -1 to correct for wrap
|
||||
|
||||
/* OCR5B and OCR5C will be used by RCOutput_APM2. Init to 0xFFFF to prevent premature PWM output */ |
||||
OCR5B = 0xFFFF; |
||||
OCR5C = 0xFFFF; |
||||
|
||||
/* Enable input capture interrupt */ |
||||
TIMSK5 |= _BV(ICIE5); |
||||
|
||||
SREG = oldSREG; |
||||
} |
||||
|
||||
bool APM2RCInput::new_input()
|
||||
{
|
||||
if (_new_input) { |
||||
_new_input = false; |
||||
return true; |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
uint8_t APM2RCInput::num_channels() { return _num_channels; } |
||||
|
||||
/* constrain captured pulse to be between min and max pulsewidth. */ |
||||
static inline uint16_t constrain_pulse(uint16_t p) { |
||||
if (p > RC_INPUT_MAX_PULSEWIDTH) return RC_INPUT_MAX_PULSEWIDTH; |
||||
if (p < RC_INPUT_MIN_PULSEWIDTH) return RC_INPUT_MIN_PULSEWIDTH; |
||||
return p; |
||||
} |
||||
|
||||
|
||||
uint16_t APM2RCInput::read(uint8_t ch) { |
||||
/* constrain ch */ |
||||
if (ch >= AVR_RC_INPUT_NUM_CHANNELS) return 0; |
||||
/* grab channel from isr's memory in critical section*/ |
||||
uint8_t oldSREG = SREG; |
||||
cli(); |
||||
uint16_t capt = _pulse_capt[ch]; |
||||
SREG = oldSREG; |
||||
/* scale _pulse_capt from 0.5us units to 1us units. */ |
||||
uint16_t pulse = constrain_pulse(capt >> 1); |
||||
/* Check for override */ |
||||
uint16_t over = _override[ch]; |
||||
return (over == 0) ? pulse : over; |
||||
} |
||||
|
||||
uint8_t APM2RCInput::read(uint16_t* periods, uint8_t len) { |
||||
/* constrain len */ |
||||
if (len > AVR_RC_INPUT_NUM_CHANNELS) { len = AVR_RC_INPUT_NUM_CHANNELS; } |
||||
/* grab channels from isr's memory in critical section */ |
||||
uint8_t oldSREG = SREG; |
||||
cli(); |
||||
for (int i = 0; i < len; i++) { |
||||
periods[i] = _pulse_capt[i]; |
||||
} |
||||
SREG = oldSREG; |
||||
/* Outside of critical section, do the math (in place) to scale and
|
||||
* constrain the pulse. */ |
||||
for (int i = 0; i < len; i++) { |
||||
/* scale _pulse_capt from 0.5us units to 1us units. */ |
||||
periods[i] = constrain_pulse(periods[i] >> 1); |
||||
/* check for override */ |
||||
if (_override[i] != 0) { |
||||
periods[i] = _override[i]; |
||||
} |
||||
} |
||||
return _num_channels; |
||||
} |
||||
|
||||
bool APM2RCInput::set_overrides(int16_t *overrides, uint8_t len) { |
||||
bool res = false; |
||||
for (int i = 0; i < len; i++) { |
||||
res |= set_override(i, overrides[i]); |
||||
} |
||||
return res; |
||||
} |
||||
|
||||
bool APM2RCInput::set_override(uint8_t channel, int16_t override) { |
||||
if (override < 0) return false; /* -1: no change. */ |
||||
if (channel < AVR_RC_INPUT_NUM_CHANNELS) { |
||||
_override[channel] = override; |
||||
if (override != 0) { |
||||
_new_input = true; |
||||
return true; |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
void APM2RCInput::clear_overrides() { |
||||
for (int i = 0; i < AVR_RC_INPUT_NUM_CHANNELS; i++) { |
||||
_override[i] = 0; |
||||
} |
||||
} |
||||
|
||||
#endif |
@ -1,61 +0,0 @@
@@ -1,61 +0,0 @@
|
||||
|
||||
#ifndef __AP_HAL_AVR_RC_OUTPUT_H__ |
||||
#define __AP_HAL_AVR_RC_OUTPUT_H__ |
||||
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#include "AP_HAL_AVR_Namespace.h" |
||||
|
||||
class AP_HAL_AVR::APM1RCOutput : public AP_HAL::RCOutput { |
||||
public: |
||||
/* No init argument required */ |
||||
void init(void* machtnichts); |
||||
|
||||
/* Output freq (1/period) control */ |
||||
void set_freq(uint32_t chmask, uint16_t freq_hz); |
||||
uint16_t get_freq(uint8_t ch); |
||||
|
||||
/* Output active/highZ control, either by single channel at a time
|
||||
* or a mask of channels */ |
||||
void enable_ch(uint8_t ch); |
||||
void disable_ch(uint8_t ch); |
||||
|
||||
/* Output, either single channel or bulk array of channels */ |
||||
void write(uint8_t ch, uint16_t period_ms); |
||||
|
||||
/* Read back current output state, as either single channel or
|
||||
* array of channels. */ |
||||
uint16_t read(uint8_t ch); |
||||
void read(uint16_t* period_ms, uint8_t len); |
||||
|
||||
private: |
||||
uint16_t _timer_period(uint16_t speed_hz); |
||||
}; |
||||
|
||||
class AP_HAL_AVR::APM2RCOutput : public AP_HAL::RCOutput { |
||||
public: |
||||
/* No init argument required */ |
||||
void init(void* machtnichts); |
||||
|
||||
/* Output freq (1/period) control */ |
||||
void set_freq(uint32_t chmask, uint16_t freq_hz); |
||||
uint16_t get_freq(uint8_t ch); |
||||
|
||||
/* Output active/highZ control, either by single channel at a time
|
||||
* or a mask of channels */ |
||||
void enable_ch(uint8_t ch); |
||||
void disable_ch(uint8_t ch); |
||||
|
||||
/* Output, either single channel or bulk array of channels */ |
||||
void write(uint8_t ch, uint16_t period_us); |
||||
|
||||
/* Read back current output state, as either single channel or
|
||||
* array of channels starting at 0. */ |
||||
uint16_t read(uint8_t ch); |
||||
void read(uint16_t* period_us, uint8_t len); |
||||
|
||||
private: |
||||
uint16_t _timer_period(uint16_t speed_hz); |
||||
}; |
||||
|
||||
#endif // __AP_HAL_AVR_RC_OUTPUT_H__
|
||||
|
@ -1,207 +0,0 @@
@@ -1,207 +0,0 @@
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#if CONFIG_HAL_BOARD == HAL_BOARD_APM1 |
||||
|
||||
#include <avr/interrupt.h> |
||||
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#include "AP_HAL_AVR.h" |
||||
#include "RCOutput.h" |
||||
using namespace AP_HAL_AVR; |
||||
|
||||
extern const AP_HAL::HAL& hal; |
||||
|
||||
/* No init argument required */ |
||||
void APM1RCOutput::init(void* machtnichts) { |
||||
// --------------------- TIMER1: CH_3, CH_4, and CH_10 ---------------
|
||||
hal.gpio->pinMode(11,HAL_GPIO_OUTPUT); // CH_10 (PB5/OC1A)
|
||||
hal.gpio->pinMode(12,HAL_GPIO_OUTPUT); // CH_3 (PB6/OC1B)
|
||||
hal.gpio->pinMode(13,HAL_GPIO_OUTPUT); // CH_4 (PB7/OC1C)
|
||||
|
||||
// WGM: 1 1 1 0. Clear Timer on Compare, TOP is ICR1.
|
||||
// CS11: prescale by 8 => 0.5us tick
|
||||
TCCR1A =((1<<WGM11)); |
||||
TCCR1B = (1<<WGM13)|(1<<WGM12)|(1<<CS11); |
||||
ICR1 = 40000; // 0.5us tick => 50hz freq
|
||||
OCR1A = 0xFFFF; // Init OCR registers to nil output signal
|
||||
OCR1B = 0xFFFF; |
||||
OCR1C = 0xFFFF; |
||||
|
||||
//--------------- TIMER3: CH_7, CH_8, and CH_11 ---------------------
|
||||
hal.gpio->pinMode(5,HAL_GPIO_OUTPUT); // CH_11 (PE3/OC3A)
|
||||
hal.gpio->pinMode(2,HAL_GPIO_OUTPUT); // CH_8 (PE4/OC3B)
|
||||
hal.gpio->pinMode(3,HAL_GPIO_OUTPUT); // CH_7 (PE5/OC3C)
|
||||
|
||||
// WGM: 1 1 1 0. Clear timer on Compare, TOP is ICR3
|
||||
// CS31: prescale by 8 => 0.5us tick
|
||||
TCCR3A =((1<<WGM31)); |
||||
TCCR3B = (1<<WGM33)|(1<<WGM32)|(1<<CS31); |
||||
OCR3A = 0xFFFF; // Init OCR registers to nil output signal
|
||||
OCR3B = 0xFFFF; |
||||
OCR3C = 0xFFFF; |
||||
ICR3 = 40000; // 0.5us tick => 50hz freq
|
||||
|
||||
//--------------- TIMER4: CH_6 and CH_5 ----------------------------
|
||||
// NB TIMER4 is shared with PPM input from RCInput_APM1.cpp
|
||||
// The TIMER4 registers are assumed to be setup already.
|
||||
hal.gpio->pinMode(7,HAL_GPIO_OUTPUT); // CH_5 (PH4/OC4B)
|
||||
hal.gpio->pinMode(8,HAL_GPIO_OUTPUT); // CH_6 (PH5/OC4C)
|
||||
|
||||
|
||||
//--------------- TIMER5: CH_1, CH_2 and CH_9 -----------------------
|
||||
hal.gpio->pinMode(46, HAL_GPIO_OUTPUT); // CH_9 (PL3/OC5A)
|
||||
hal.gpio->pinMode(45, HAL_GPIO_OUTPUT); // CH_1 (PL4/OC5B)
|
||||
hal.gpio->pinMode(44, HAL_GPIO_OUTPUT); // CH_2 (PL5/OC5C)
|
||||
|
||||
// WGM: 1 1 1 0. Clear timer on Compare, TOP is ICR5
|
||||
// CS51: prescale by 8 => 0.5us tick
|
||||
TCCR5A =((1<<WGM51)); |
||||
TCCR5B = (1<<WGM53)|(1<<WGM52)|(1<<CS51); |
||||
OCR5A = 0xFFFF; // Init OCR registers to nil output signal
|
||||
OCR5B = 0xFFFF; |
||||
OCR5C = 0xFFFF; |
||||
ICR5 = 40000; // 0.5us tick => 50hz freq
|
||||
} |
||||
|
||||
/* Output freq (1/period) control */ |
||||
void APM1RCOutput::set_freq(uint32_t chmask, uint16_t freq_hz) { |
||||
uint16_t icr = _timer_period(freq_hz); |
||||
|
||||
if ((chmask & ( _BV(CH_1) | _BV(CH_2) | _BV(CH_9))) != 0) { |
||||
ICR5 = icr; |
||||
} |
||||
|
||||
if ((chmask & ( _BV(CH_3) | _BV(CH_4) | _BV(CH_10))) != 0) { |
||||
ICR1 = icr; |
||||
} |
||||
|
||||
if ((chmask & ( _BV(CH_7) | _BV(CH_8) | _BV(CH_11))) != 0) { |
||||
ICR3 = icr; |
||||
} |
||||
/* No change permitted for CH_5 and CH_6 - that ICR register is
|
||||
* shared with the input capture for RCInput */ |
||||
} |
||||
|
||||
uint16_t APM1RCOutput::get_freq(uint8_t ch) { |
||||
uint16_t icr; |
||||
switch (ch) { |
||||
case CH_3: |
||||
case CH_4: |
||||
case CH_10: |
||||
icr = ICR1; |
||||
break; |
||||
/* CH_5 and CH_6 share TIMER4 with input capture.
|
||||
* The period is specified in OCR4A rather than the ICR. */ |
||||
case CH_5: |
||||
case CH_6: |
||||
icr = OCR4A; |
||||
break;
|
||||
case CH_7: |
||||
case CH_8: |
||||
case CH_11: |
||||
icr = ICR3; |
||||
break; |
||||
case CH_1: |
||||
case CH_2: |
||||
case CH_9: |
||||
icr = ICR5; |
||||
break; |
||||
default: |
||||
return 0; |
||||
} |
||||
/* transform to period by inverse of _time_period(icr). */ |
||||
return (2000000UL / icr); |
||||
} |
||||
|
||||
/* Output active/highZ control, either by single channel at a time
|
||||
* or a mask of channels */ |
||||
void APM1RCOutput::enable_ch(uint8_t ch) { |
||||
switch(ch) { |
||||
case 0: TCCR5A |= (1<<COM5B1); break; // CH_1 : OC5B
|
||||
case 1: TCCR5A |= (1<<COM5C1); break; // CH_2 : OC5C
|
||||
case 2: TCCR1A |= (1<<COM1B1); break; // CH_3 : OC1B
|
||||
case 3: TCCR1A |= (1<<COM1C1); break; // CH_4 : OC1C
|
||||
case 4: TCCR4A |= (1<<COM4C1); break; // CH_5 : OC4C
|
||||
case 5: TCCR4A |= (1<<COM4B1); break; // CH_6 : OC4B
|
||||
case 6: TCCR3A |= (1<<COM3C1); break; // CH_7 : OC3C
|
||||
case 7: TCCR3A |= (1<<COM3B1); break; // CH_8 : OC3B
|
||||
case 8: TCCR5A |= (1<<COM5A1); break; // CH_9 : OC5A
|
||||
case 9: TCCR1A |= (1<<COM1A1); break; // CH_10: OC1A
|
||||
case 10: TCCR3A |= (1<<COM3A1); break; // CH_11: OC3A
|
||||
} |
||||
} |
||||
|
||||
void APM1RCOutput::disable_ch(uint8_t ch) { |
||||
switch(ch) { |
||||
case 0: TCCR5A &= ~(1<<COM5B1); break; // CH_1 : OC5B
|
||||
case 1: TCCR5A &= ~(1<<COM5C1); break; // CH_2 : OC5C
|
||||
case 2: TCCR1A &= ~(1<<COM1B1); break; // CH_3 : OC1B
|
||||
case 3: TCCR1A &= ~(1<<COM1C1); break; // CH_4 : OC1C
|
||||
case 4: TCCR4A &= ~(1<<COM4C1); break; // CH_5 : OC4C
|
||||
case 5: TCCR4A &= ~(1<<COM4B1); break; // CH_6 : OC4B
|
||||
case 6: TCCR3A &= ~(1<<COM3C1); break; // CH_7 : OC3C
|
||||
case 7: TCCR3A &= ~(1<<COM3B1); break; // CH_8 : OC3B
|
||||
case 8: TCCR5A &= ~(1<<COM5A1); break; // CH_9 : OC5A
|
||||
case 9: TCCR1A &= ~(1<<COM1A1); break; // CH_10: OC1A
|
||||
case 10: TCCR3A &= ~(1<<COM3A1); break; // CH_11: OC3A
|
||||
} |
||||
} |
||||
|
||||
/* constrain pwm to be between min and max pulsewidth. */ |
||||
static inline uint16_t constrain_period(uint16_t p) { |
||||
if (p > RC_OUTPUT_MAX_PULSEWIDTH) return RC_OUTPUT_MAX_PULSEWIDTH; |
||||
if (p < RC_OUTPUT_MIN_PULSEWIDTH) return RC_OUTPUT_MIN_PULSEWIDTH; |
||||
return p; |
||||
} |
||||
|
||||
/* Output, either single channel or bulk array of channels */ |
||||
void APM1RCOutput::write(uint8_t ch, uint16_t period_us) { |
||||
/* constrain, then scale from 1us resolution (input units)
|
||||
* to 0.5us (timer units) */ |
||||
uint16_t pwm = constrain_period(period_us) << 1; |
||||
switch(ch) |
||||
{ |
||||
case 0: OCR5B=pwm; break; //ch1
|
||||
case 1: OCR5C=pwm; break; //ch2
|
||||
case 2: OCR1B=pwm; break; //ch3
|
||||
case 3: OCR1C=pwm; break; //ch4
|
||||
case 4: OCR4C=pwm; break; //ch5
|
||||
case 5: OCR4B=pwm; break; //ch6
|
||||
case 6: OCR3C=pwm; break; //ch7
|
||||
case 7: OCR3B=pwm; break; //ch8
|
||||
case 8: OCR5A=pwm; break; //ch9, PL3
|
||||
case 9: OCR1A=pwm; break; //ch10, PB5
|
||||
case 10: OCR3A=pwm; break; //ch11, PE3
|
||||
} |
||||
} |
||||
|
||||
/* Read back current output state, as either single channel or
|
||||
* array of channels. */ |
||||
uint16_t APM1RCOutput::read(uint8_t ch) { |
||||
uint16_t pwm=0; |
||||
switch(ch) { |
||||
case 0: pwm=OCR5B; break; //ch1
|
||||
case 1: pwm=OCR5C; break; //ch2
|
||||
case 2: pwm=OCR1B; break; //ch3
|
||||
case 3: pwm=OCR1C; break; //ch4
|
||||
case 4: pwm=OCR4C; break; //ch5
|
||||
case 5: pwm=OCR4B; break; //ch6
|
||||
case 6: pwm=OCR3C; break; //ch7
|
||||
case 7: pwm=OCR3B; break; //ch8
|
||||
case 8: pwm=OCR5A; break; //ch9, PL3
|
||||
case 9: pwm=OCR1A; break; //ch10, PB5
|
||||
case 10: pwm=OCR3A; break; //ch11, PE3
|
||||
} |
||||
/* scale from 0.5us resolution (timer units) to 1us units */ |
||||
return pwm>>1; |
||||
} |
||||
|
||||
void APM1RCOutput::read(uint16_t* period_us, uint8_t len) { |
||||
for (int i = 0; i < len; i++) { |
||||
period_us[i] = read(i); |
||||
} |
||||
} |
||||
|
||||
uint16_t APM1RCOutput::_timer_period(uint16_t speed_hz) { |
||||
return 2000000UL / speed_hz; |
||||
} |
||||
#endif |
@ -1,199 +0,0 @@
@@ -1,199 +0,0 @@
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#if CONFIG_HAL_BOARD == HAL_BOARD_APM2 |
||||
|
||||
#include <avr/interrupt.h> |
||||
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#include "AP_HAL_AVR.h" |
||||
#include "RCOutput.h" |
||||
using namespace AP_HAL_AVR; |
||||
|
||||
extern const AP_HAL::HAL& hal; |
||||
|
||||
/* No init argument required */ |
||||
void APM2RCOutput::init(void* machtnichts) { |
||||
// --------------------- TIMER1: CH_1 and CH_2 -----------------------
|
||||
hal.gpio->pinMode(12,HAL_GPIO_OUTPUT); // CH_1 (PB6/OC1B)
|
||||
hal.gpio->pinMode(11,HAL_GPIO_OUTPUT); // CH_2 (PB5/OC1A)
|
||||
|
||||
// WGM: 1 1 1 0. Clear Timer on Compare, TOP is ICR1.
|
||||
// CS11: prescale by 8 => 0.5us tick
|
||||
TCCR1A =((1<<WGM11)); |
||||
TCCR1B = (1<<WGM13)|(1<<WGM12)|(1<<CS11); |
||||
ICR1 = 40000; // 0.5us tick => 50hz freq
|
||||
OCR1A = 0xFFFF; // Init OCR registers to nil output signal
|
||||
OCR1B = 0xFFFF; |
||||
|
||||
// --------------- TIMER4: CH_3, CH_4, and CH_5 ---------------------
|
||||
hal.gpio->pinMode(8,HAL_GPIO_OUTPUT); // CH_3 (PH5/OC4C)
|
||||
hal.gpio->pinMode(7,HAL_GPIO_OUTPUT); // CH_4 (PH4/OC4B)
|
||||
hal.gpio->pinMode(6,HAL_GPIO_OUTPUT); // CH_5 (PH3/OC4A)
|
||||
|
||||
// WGM: 1 1 1 0. Clear Timer on Compare, TOP is ICR4.
|
||||
// CS41: prescale by 8 => 0.5us tick
|
||||
TCCR4A =((1<<WGM41)); |
||||
TCCR4B = (1<<WGM43)|(1<<WGM42)|(1<<CS41); |
||||
OCR4A = 0xFFFF; // Init OCR registers to nil output signal
|
||||
OCR4B = 0xFFFF; |
||||
OCR4C = 0xFFFF; |
||||
ICR4 = 40000; // 0.5us tick => 50hz freq
|
||||
|
||||
//--------------- TIMER3: CH_6, CH_7, and CH_8 ----------------------
|
||||
hal.gpio->pinMode(3,HAL_GPIO_OUTPUT); // CH_6 (PE5/OC3C)
|
||||
hal.gpio->pinMode(2,HAL_GPIO_OUTPUT); // CH_7 (PE4/OC3B)
|
||||
hal.gpio->pinMode(5,HAL_GPIO_OUTPUT); // CH_8 (PE3/OC3A)
|
||||
|
||||
// WGM: 1 1 1 0. Clear timer on Compare, TOP is ICR3
|
||||
// CS31: prescale by 8 => 0.5us tick
|
||||
TCCR3A =((1<<WGM31)); |
||||
TCCR3B = (1<<WGM33)|(1<<WGM32)|(1<<CS31); |
||||
OCR3A = 0xFFFF; // Init OCR registers to nil output signal
|
||||
OCR3B = 0xFFFF; |
||||
OCR3C = 0xFFFF; |
||||
ICR3 = 40000; // 0.5us tick => 50hz freq
|
||||
|
||||
//--------------- TIMER5: CH_10, and CH_11 ---------------
|
||||
// NB TIMER5 is shared with PPM input from RCInput_APM2.cpp
|
||||
// The TIMER5 registers are assumed to be setup already.
|
||||
hal.gpio->pinMode(45, HAL_GPIO_OUTPUT); // CH_10 (PL4/OC5B)
|
||||
hal.gpio->pinMode(44, HAL_GPIO_OUTPUT); // CH_11 (PL5/OC5C)
|
||||
} |
||||
|
||||
/* Output freq (1/period) control */ |
||||
void APM2RCOutput::set_freq(uint32_t chmask, uint16_t freq_hz) { |
||||
uint16_t icr = _timer_period(freq_hz); |
||||
|
||||
if ((chmask & ( _BV(CH_1) | _BV(CH_2))) != 0) { |
||||
ICR1 = icr; |
||||
} |
||||
|
||||
if ((chmask & ( _BV(CH_3) | _BV(CH_4) | _BV(CH_5))) != 0) { |
||||
ICR4 = icr; |
||||
} |
||||
|
||||
if ((chmask & ( _BV(CH_6) | _BV(CH_7) | _BV(CH_8))) != 0) { |
||||
ICR3 = icr; |
||||
} |
||||
} |
||||
|
||||
uint16_t APM2RCOutput::get_freq(uint8_t ch) { |
||||
uint16_t icr; |
||||
switch (ch) { |
||||
case CH_1: |
||||
case CH_2: |
||||
icr = ICR1; |
||||
break; |
||||
case CH_3: |
||||
case CH_4: |
||||
case CH_5: |
||||
icr = ICR4; |
||||
break;
|
||||
case CH_6: |
||||
case CH_7: |
||||
case CH_8: |
||||
icr = ICR3; |
||||
break; |
||||
/* CH_10 and CH_11 share TIMER5 with input capture.
|
||||
* The period is specified in OCR5A rater than the ICR. */ |
||||
case CH_10: |
||||
case CH_11: |
||||
icr = OCR5A; |
||||
break; |
||||
default: |
||||
return 0; |
||||
} |
||||
/* transform to period by inverse of _time_period(icr). */ |
||||
return (2000000UL / icr); |
||||
} |
||||
|
||||
/* Output active/highZ control, either by single channel at a time
|
||||
* or a mask of channels */ |
||||
void APM2RCOutput::enable_ch(uint8_t ch) { |
||||
switch(ch) { |
||||
case 0: TCCR1A |= (1<<COM1B1); break; // CH_1 : OC1B
|
||||
case 1: TCCR1A |= (1<<COM1A1); break; // CH_2 : OC1A
|
||||
case 2: TCCR4A |= (1<<COM4C1); break; // CH_3 : OC4C
|
||||
case 3: TCCR4A |= (1<<COM4B1); break; // CH_4 : OC4B
|
||||
case 4: TCCR4A |= (1<<COM4A1); break; // CH_5 : OC4A
|
||||
case 5: TCCR3A |= (1<<COM3C1); break; // CH_6 : OC3C
|
||||
case 6: TCCR3A |= (1<<COM3B1); break; // CH_7 : OC3B
|
||||
case 7: TCCR3A |= (1<<COM3A1); break; // CH_8 : OC3A
|
||||
case 9: TCCR5A |= (1<<COM5B1); break; // CH_10 : OC5B
|
||||
case 10: TCCR5A |= (1<<COM5C1); break; // CH_11 : OC5C
|
||||
} |
||||
} |
||||
|
||||
void APM2RCOutput::disable_ch(uint8_t ch) { |
||||
switch(ch) { |
||||
case 0: TCCR1A &= ~(1<<COM1B1); break; // CH_1 : OC1B
|
||||
case 1: TCCR1A &= ~(1<<COM1A1); break; // CH_2 : OC1A
|
||||
case 2: TCCR4A &= ~(1<<COM4C1); break; // CH_3 : OC4C
|
||||
case 3: TCCR4A &= ~(1<<COM4B1); break; // CH_4 : OC4B
|
||||
case 4: TCCR4A &= ~(1<<COM4A1); break; // CH_5 : OC4A
|
||||
case 5: TCCR3A &= ~(1<<COM3C1); break; // CH_6 : OC3C
|
||||
case 6: TCCR3A &= ~(1<<COM3B1); break; // CH_7 : OC3B
|
||||
case 7: TCCR3A &= ~(1<<COM3A1); break; // CH_8 : OC3A
|
||||
case 9: TCCR5A &= ~(1<<COM5B1); break; // CH_10 : OC5B
|
||||
case 10: TCCR5A &= ~(1<<COM5C1); break; // CH_11 : OC5C
|
||||
} |
||||
} |
||||
|
||||
/* constrain pwm to be between min and max pulsewidth. */ |
||||
static inline uint16_t constrain_period(uint16_t p) { |
||||
if (p > RC_OUTPUT_MAX_PULSEWIDTH) return RC_OUTPUT_MAX_PULSEWIDTH; |
||||
if (p < RC_OUTPUT_MIN_PULSEWIDTH) return RC_OUTPUT_MIN_PULSEWIDTH; |
||||
return p; |
||||
} |
||||
|
||||
/* Output, either single channel or bulk array of channels */ |
||||
void APM2RCOutput::write(uint8_t ch, uint16_t period_us) { |
||||
/* constrain, then scale from 1us resolution (input units)
|
||||
* to 0.5us (timer units) */ |
||||
uint16_t pwm = constrain_period(period_us) << 1; |
||||
switch(ch) |
||||
{ |
||||
case 0: OCR1B=pwm; break; // out1
|
||||
case 1: OCR1A=pwm; break; // out2
|
||||
case 2: OCR4C=pwm; break; // out3
|
||||
case 3: OCR4B=pwm; break; // out4
|
||||
case 4: OCR4A=pwm; break; // out5
|
||||
case 5: OCR3C=pwm; break; // out6
|
||||
case 6: OCR3B=pwm; break; // out7
|
||||
case 7: OCR3A=pwm; break; // out8
|
||||
case 9: OCR5B=pwm; break; // out10
|
||||
case 10: OCR5C=pwm; break; // out11
|
||||
} |
||||
} |
||||
|
||||
/* Read back current output state, as either single channel or
|
||||
* array of channels. */ |
||||
uint16_t APM2RCOutput::read(uint8_t ch) { |
||||
uint16_t pwm=0; |
||||
switch(ch) { |
||||
case 0: pwm=OCR1B; break; // out1
|
||||
case 1: pwm=OCR1A; break; // out2
|
||||
case 2: pwm=OCR4C; break; // out3
|
||||
case 3: pwm=OCR4B; break; // out4
|
||||
case 4: pwm=OCR4A; break; // out5
|
||||
case 5: pwm=OCR3C; break; // out6
|
||||
case 6: pwm=OCR3B; break; // out7
|
||||
case 7: pwm=OCR3A; break; // out8
|
||||
case 9: pwm=OCR5B; break; // out10
|
||||
case 10: pwm=OCR5C; break; // out11
|
||||
} |
||||
/* scale from 0.5us resolution (timer units) to 1us units */ |
||||
return pwm>>1; |
||||
|
||||
} |
||||
|
||||
void APM2RCOutput::read(uint16_t* period_us, uint8_t len) { |
||||
for (int i = 0; i < len; i++) { |
||||
period_us[i] = read(i); |
||||
} |
||||
} |
||||
|
||||
uint16_t APM2RCOutput::_timer_period(uint16_t speed_hz) { |
||||
return 2000000UL / speed_hz; |
||||
} |
||||
|
||||
#endif |
@ -0,0 +1 @@
@@ -0,0 +1 @@
|
||||
AVR is only supported on its separate [branch](https://github.com/diydrones/ardupilot/tree/master-AVR]) |
@ -1,52 +0,0 @@
@@ -1,52 +0,0 @@
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#if CONFIG_HAL_BOARD == HAL_BOARD_APM1 |
||||
|
||||
#include <avr/io.h> |
||||
#include <AP_HAL/AP_HAL.h> |
||||
#include "SPIDriver.h" |
||||
#include "SPIDevices.h" |
||||
#include "GPIO.h" |
||||
#include "utility/pins_arduino_mega.h" |
||||
using namespace AP_HAL_AVR; |
||||
|
||||
extern const AP_HAL::HAL& hal; |
||||
|
||||
void APM1SPIDeviceManager::init(void* machtnichts) { |
||||
/* dataflow cs is on arduino pin 53, PORTB0 */ |
||||
AVRDigitalSource* df_cs = new AVRDigitalSource(_BV(0), PB); |
||||
/* dataflash: divide clock by 2 to 8Mhz, set SPI_MODE_3
|
||||
* spcr gets 0x0C to set SPI_MODE_3 |
||||
* spsr gets bit SPI2X for clock divider */ |
||||
_dataflash = new AVRSPI0DeviceDriver(df_cs, 0x0C, 0x0C, _BV(SPI2X)); |
||||
_dataflash->init(); |
||||
|
||||
/* optflow cs is on Arduino pin 34, PORTC3 */ |
||||
AVRDigitalSource* opt_cs = new AVRDigitalSource(_BV(3), PC); |
||||
/* optflow: divide clock by 8 to 2Mhz
|
||||
* spcr gets bit SPR0, spsr gets bit SPI2X */ |
||||
_optflow = new AVRSPI0DeviceDriver(opt_cs, _BV(SPR0), _BV(SPR0), 0); |
||||
_optflow->init(); |
||||
|
||||
/* adc cs is on Arduino pin 33, PORTC4 */ |
||||
AVRDigitalSource* adc_cs = new AVRDigitalSource(_BV(4), PC); |
||||
/* adc: ubbr2 gets value of 2 to run at 2.6Mhz
|
||||
* (config value cribbed from AP_ADC_ADS7844 driver pre-port) */ |
||||
_adc = new AVRSPI2DeviceDriver(adc_cs, 0, 2); |
||||
_adc->init(); |
||||
} |
||||
|
||||
AP_HAL::SPIDeviceDriver* APM1SPIDeviceManager::device(enum AP_HAL::SPIDevice d)
|
||||
{ |
||||
switch (d) { |
||||
case AP_HAL::SPIDevice_Dataflash: |
||||
return _dataflash; |
||||
case AP_HAL::SPIDevice_ADS7844: |
||||
return _adc; |
||||
case AP_HAL::SPIDevice_ADNS3080_SPI0: |
||||
return _optflow; |
||||
default: |
||||
return NULL; |
||||
}; |
||||
} |
||||
|
||||
#endif |
@ -1,81 +0,0 @@
@@ -1,81 +0,0 @@
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#if CONFIG_HAL_BOARD == HAL_BOARD_APM2 |
||||
|
||||
#include <avr/io.h> |
||||
#include <AP_HAL/AP_HAL.h> |
||||
#include "SPIDriver.h" |
||||
#include "SPIDevices.h" |
||||
#include "utility/pins_arduino_mega.h" |
||||
using namespace AP_HAL_AVR; |
||||
|
||||
extern const AP_HAL::HAL& hal; |
||||
|
||||
void APM2SPIDeviceManager::init(void* machtnichts) { |
||||
|
||||
/* Note that the order of the init() of the MS5611 and MPU6k is
|
||||
* critical for the APM2. If you initialise in the wrong order |
||||
* then the MS5611 doesn't initialise itself correctly. This |
||||
* indicates an electrical fault in the APM2 which needs to be |
||||
* investigated. Meanwhile, initialising the MPU6k CS pin before |
||||
* the MS5611 CS pin works around the problem |
||||
*/ |
||||
|
||||
#define SPI0_SPCR_8MHz 0 |
||||
#define SPI0_SPSR_8MHz _BV(SPI2X) |
||||
#define SPI0_SPCR_500kHz _BV(SPR1) |
||||
#define SPI0_SPSR_500kHz _BV(SPI2X) |
||||
|
||||
/* mpu6k cs is on Arduino pin 53, PORTB0 */ |
||||
AVRDigitalSource* mpu6k_cs = new AVRDigitalSource(_BV(0), PB); |
||||
/* mpu6k: run clock at 8MHz in high speed mode and 512kHz for low
|
||||
* speed */ |
||||
_mpu6k = new AVRSPI0DeviceDriver(mpu6k_cs, SPI0_SPCR_500kHz, SPI0_SPCR_8MHz, SPI0_SPSR_8MHz); |
||||
_mpu6k->init(); |
||||
|
||||
/* ms5611 cs is on Arduino pin 40, PORTG1 */ |
||||
AVRDigitalSource* ms5611_cs = new AVRDigitalSource(_BV(1), PG); |
||||
/* ms5611: run clock at 8MHz */ |
||||
_ms5611 = new AVRSPI0DeviceDriver(ms5611_cs, SPI0_SPCR_500kHz, SPI0_SPCR_8MHz, SPI0_SPSR_8MHz); |
||||
_ms5611->init(); |
||||
|
||||
/* optflow cs is on Arduino pin A3, PORTF3 */ |
||||
AVRDigitalSource* optflow_cs = new AVRDigitalSource(_BV(3), PF); |
||||
/* optflow: divide clock by 8 to 2Mhz
|
||||
* spcr gets bit SPR0, spsr gets bit SPI2X */ |
||||
_optflow_spi0 = new AVRSPI0DeviceDriver(optflow_cs, _BV(SPR0)|_BV(CPOL)|_BV(CPHA), _BV(SPR0)|_BV(CPOL)|_BV(CPHA), _BV(SPI2X)); |
||||
_optflow_spi0->init(); |
||||
|
||||
/* Dataflash CS is on Arduino pin 28, PORTA6 */ |
||||
AVRDigitalSource* df_cs = new AVRDigitalSource(_BV(6), PA); |
||||
/* dataflash uses mode 0 and a clock of 8mhz
|
||||
* ucsr3c = 0
|
||||
* ubrr3 = 0 */ |
||||
_dataflash = new AVRSPI3DeviceDriver(df_cs, 0, 0); |
||||
_dataflash->init(); |
||||
|
||||
/* optflow uses mode 3 and a clock of 2mhz
|
||||
* ucsr3c = _BV(UCPHA3N)|_BV(UCPOL3) = 3 |
||||
* ubrr3 = 3 */ |
||||
_optflow_spi3 = new AVRSPI3DeviceDriver(optflow_cs, 3, 3); |
||||
_optflow_spi3->init(); |
||||
} |
||||
|
||||
AP_HAL::SPIDeviceDriver* APM2SPIDeviceManager::device(enum AP_HAL::SPIDevice d)
|
||||
{ |
||||
switch (d) { |
||||
case AP_HAL::SPIDevice_Dataflash: |
||||
return _dataflash; |
||||
case AP_HAL::SPIDevice_MS5611: |
||||
return _ms5611; |
||||
case AP_HAL::SPIDevice_MPU6000: |
||||
return _mpu6k; |
||||
case AP_HAL::SPIDevice_ADNS3080_SPI0: |
||||
return _optflow_spi0; |
||||
case AP_HAL::SPIDevice_ADNS3080_SPI3: |
||||
return _optflow_spi3; |
||||
default: |
||||
return NULL; |
||||
}; |
||||
} |
||||
|
||||
#endif |
@ -1,160 +0,0 @@
@@ -1,160 +0,0 @@
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#if (CONFIG_HAL_BOARD == HAL_BOARD_APM1 || CONFIG_HAL_BOARD == HAL_BOARD_APM2) |
||||
|
||||
#include <avr/io.h> |
||||
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#include "SPIDevices.h" |
||||
#include "GPIO.h" |
||||
#include "Semaphores.h" |
||||
#include "utility/pins_arduino_mega.h" |
||||
using namespace AP_HAL_AVR; |
||||
|
||||
extern const AP_HAL::HAL& hal; |
||||
|
||||
#define SPI0_MISO_PIN 50 |
||||
#define SPI0_MOSI_PIN 51 |
||||
#define SPI0_SCK_PIN 52 |
||||
|
||||
AVRSemaphore AVRSPI0DeviceDriver::_semaphore; |
||||
bool AVRSPI0DeviceDriver::_force_low_speed; |
||||
|
||||
static volatile bool spi0_transferflag = false; |
||||
|
||||
void AVRSPI0DeviceDriver::init() { |
||||
hal.gpio->pinMode(SPI0_MISO_PIN, HAL_GPIO_INPUT); |
||||
hal.gpio->pinMode(SPI0_MOSI_PIN, HAL_GPIO_OUTPUT); |
||||
hal.gpio->pinMode(SPI0_SCK_PIN, HAL_GPIO_OUTPUT); |
||||
|
||||
_cs_pin->mode(HAL_GPIO_OUTPUT); |
||||
_cs_pin->write(1); |
||||
|
||||
/* Enable the SPI0 peripheral as a master */ |
||||
SPCR = _BV(SPE) | _BV(MSTR); |
||||
} |
||||
|
||||
AP_HAL::Semaphore* AVRSPI0DeviceDriver::get_semaphore() { |
||||
return &_semaphore; |
||||
} |
||||
|
||||
void AVRSPI0DeviceDriver::_cs_assert()
|
||||
{ |
||||
const uint8_t valid_spcr_mask =
|
||||
(_BV(CPOL) | _BV(CPHA) | _BV(SPR1) | _BV(SPR0)); |
||||
if (_force_low_speed) { |
||||
_spcr = _spcr_lowspeed; |
||||
} |
||||
uint8_t new_spcr = (SPCR & ~valid_spcr_mask) | (_spcr & valid_spcr_mask); |
||||
SPCR = new_spcr;
|
||||
|
||||
const uint8_t valid_spsr_mask = _BV(SPI2X); |
||||
uint8_t new_spsr = (SPSR & ~valid_spsr_mask) | (_spsr & valid_spsr_mask); |
||||
SPSR = new_spsr; |
||||
|
||||
_cs_pin->write(0); |
||||
} |
||||
|
||||
void AVRSPI0DeviceDriver::_cs_release()
|
||||
{ |
||||
_cs_pin->write(1); |
||||
} |
||||
|
||||
uint8_t AVRSPI0DeviceDriver::_transfer(uint8_t data)
|
||||
{ |
||||
if (spi0_transferflag) { |
||||
hal.scheduler->panic(PSTR("PANIC: SPI0 transfer collision")); |
||||
} |
||||
spi0_transferflag = true; |
||||
SPDR = data; |
||||
if (SPSR & _BV(WCOL)) { |
||||
hal.scheduler->panic(PSTR("PANIC: SPI0 write collision")); |
||||
return 0; |
||||
} |
||||
while(!(SPSR & _BV(SPIF))); |
||||
uint8_t read_spdr = SPDR; |
||||
spi0_transferflag = false; |
||||
return read_spdr; |
||||
} |
||||
|
||||
/**
|
||||
a specialised transfer function for the MPU6k. This saves 2 usec |
||||
per byte |
||||
*/ |
||||
void AVRSPI0DeviceDriver::_transfer16(const uint8_t *tx, uint8_t *rx)
|
||||
{ |
||||
spi0_transferflag = true; |
||||
#define TRANSFER1(i) do { SPDR = tx[i]; while(!(SPSR & _BV(SPIF))); rx[i] = SPDR; } while(0) |
||||
TRANSFER1(0); |
||||
TRANSFER1(1); |
||||
TRANSFER1(2); |
||||
TRANSFER1(3); |
||||
TRANSFER1(4); |
||||
TRANSFER1(5); |
||||
TRANSFER1(6); |
||||
TRANSFER1(7); |
||||
TRANSFER1(8); |
||||
TRANSFER1(9); |
||||
TRANSFER1(10); |
||||
TRANSFER1(11); |
||||
TRANSFER1(12); |
||||
TRANSFER1(13); |
||||
TRANSFER1(14); |
||||
TRANSFER1(15); |
||||
spi0_transferflag = false; |
||||
} |
||||
|
||||
void AVRSPI0DeviceDriver::transfer(const uint8_t *tx, uint16_t len) { |
||||
for (uint16_t i = 0; i < len; i++) { |
||||
_transfer(tx[i]); |
||||
} |
||||
} |
||||
|
||||
bool AVRSPI0DeviceDriver::transaction(const uint8_t *tx, uint8_t *rx, |
||||
uint16_t len) { |
||||
_cs_assert(); |
||||
if (rx == NULL) { |
||||
for (uint16_t i = 0; i < len; i++) { |
||||
_transfer(tx[i]); |
||||
} |
||||
} else { |
||||
while (len >= 16) { |
||||
_transfer16(tx, rx); |
||||
tx += 16; |
||||
rx += 16; |
||||
len -= 16; |
||||
} |
||||
for (uint16_t i = 0; i < len; i++) { |
||||
rx[i] = _transfer(tx[i]); |
||||
} |
||||
} |
||||
_cs_release(); |
||||
return true; |
||||
} |
||||
|
||||
void AVRSPI0DeviceDriver::cs_assert() { |
||||
_cs_assert(); |
||||
} |
||||
|
||||
void AVRSPI0DeviceDriver::cs_release() { |
||||
_cs_release(); |
||||
} |
||||
|
||||
uint8_t AVRSPI0DeviceDriver::transfer(uint8_t data) { |
||||
return _transfer(data); |
||||
} |
||||
|
||||
/**
|
||||
allow on the fly bus speed changes for MPU6000 |
||||
*/ |
||||
void AVRSPI0DeviceDriver::set_bus_speed(AVRSPI0DeviceDriver::bus_speed speed)
|
||||
{ |
||||
if (speed == AVRSPI0DeviceDriver::SPI_SPEED_HIGH) { |
||||
_spcr = _spcr_highspeed; |
||||
_force_low_speed = false; |
||||
} else { |
||||
_spcr = _spcr_lowspeed; |
||||
_force_low_speed = true; |
||||
} |
||||
} |
||||
|
||||
#endif |
@ -1,139 +0,0 @@
@@ -1,139 +0,0 @@
|
||||
/// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*-
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#if (CONFIG_HAL_BOARD == HAL_BOARD_APM1 || CONFIG_HAL_BOARD == HAL_BOARD_APM2) |
||||
|
||||
#include <avr/io.h> |
||||
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#include "SPIDevices.h" |
||||
#include "GPIO.h" |
||||
#include "Semaphores.h" |
||||
#include "utility/pins_arduino_mega.h" |
||||
using namespace AP_HAL_AVR; |
||||
|
||||
extern const AP_HAL::HAL& hal; |
||||
|
||||
AVRSemaphore AVRSPI2DeviceDriver::_semaphore; |
||||
|
||||
void AVRSPI2DeviceDriver::init() { |
||||
AVRDigitalSource spi2_miso(_BV(0), PH); |
||||
spi2_miso.mode(HAL_GPIO_INPUT); |
||||
|
||||
AVRDigitalSource spi2_mosi(_BV(1), PH); |
||||
spi2_mosi.mode(HAL_GPIO_OUTPUT); |
||||
|
||||
AVRDigitalSource spi2_sck(_BV(2), PH); |
||||
spi2_sck.mode(HAL_GPIO_OUTPUT); |
||||
|
||||
/* UMSELn1 and UMSELn2: USART in SPI Master mode */ |
||||
UCSR2C = _BV(UMSEL21) | _BV(UMSEL20); |
||||
/* Enable RX and TX. */ |
||||
UCSR2B = _BV(RXEN2) | _BV(TXEN2); |
||||
|
||||
/* Setup chip select pin */ |
||||
_cs_pin->mode(HAL_GPIO_OUTPUT); |
||||
_cs_pin->write(1); |
||||
} |
||||
|
||||
AP_HAL::Semaphore* AVRSPI2DeviceDriver::get_semaphore() { |
||||
return &_semaphore; |
||||
} |
||||
|
||||
inline void AVRSPI2DeviceDriver::_cs_assert() { |
||||
/* set the device UCSRnC configuration bits.
|
||||
* only sets data order, clock phase, and clock polarity bits (lowest |
||||
* three bits) */ |
||||
const uint8_t new_ucsr2c = (UCSR2C & ~0x07) | (_ucsr2c & (0x07)); |
||||
UCSR2C = new_ucsr2c; |
||||
/* set the device baud rate */ |
||||
UBRR2 = _ubrr2; |
||||
|
||||
_cs_pin->write(0); |
||||
} |
||||
|
||||
inline void AVRSPI2DeviceDriver::_cs_release() { |
||||
_cs_pin->write(1); |
||||
} |
||||
|
||||
inline uint8_t AVRSPI2DeviceDriver::_transfer(uint8_t data) { |
||||
/* Wait for empty transmit buffer */ |
||||
while ( !( UCSR2A & _BV(UDRE2)) ) ; |
||||
|
||||
/* Put data into buffer, sends the data */ |
||||
UDR2 = data; |
||||
|
||||
/* Wait for data to be received */ |
||||
while ( !(UCSR2A & _BV(RXC2)) ) ; |
||||
|
||||
/* Get and return received data from buffer */ |
||||
return UDR2; |
||||
} |
||||
|
||||
/**
|
||||
a specialist transfer function for the APM1 ADC |
||||
*/ |
||||
void AVRSPI2DeviceDriver::_transfer17(const uint8_t *tx, uint8_t *rx)
|
||||
{ |
||||
#define TRANSFER1(i) do { while ( !( UCSR2A & _BV(UDRE2)) ); \ |
||||
UDR2 = tx[i]; \
|
||||
while ( !(UCSR2A & _BV(RXC2)) ) ; \
|
||||
rx[i] = UDR2; } while (0) |
||||
TRANSFER1(0); |
||||
TRANSFER1(1); |
||||
TRANSFER1(2); |
||||
TRANSFER1(3); |
||||
TRANSFER1(4); |
||||
TRANSFER1(5); |
||||
TRANSFER1(6); |
||||
TRANSFER1(7); |
||||
TRANSFER1(8); |
||||
TRANSFER1(9); |
||||
TRANSFER1(10); |
||||
TRANSFER1(11); |
||||
TRANSFER1(12); |
||||
TRANSFER1(13); |
||||
TRANSFER1(14); |
||||
TRANSFER1(15); |
||||
TRANSFER1(16); |
||||
} |
||||
|
||||
bool AVRSPI2DeviceDriver::transaction(const uint8_t *tx, uint8_t *rx, |
||||
uint16_t len) { |
||||
_cs_assert(); |
||||
if (rx == NULL) { |
||||
for (uint16_t i = 0; i < len; i++) { |
||||
_transfer(tx[i]); |
||||
} |
||||
} else { |
||||
while (len >= 17) { |
||||
_transfer17(tx, rx); |
||||
tx += 17; |
||||
rx += 17; |
||||
len -= 17; |
||||
} |
||||
for (uint16_t i = 0; i < len; i++) { |
||||
rx[i] = _transfer(tx[i]); |
||||
} |
||||
} |
||||
_cs_release(); |
||||
return true; |
||||
} |
||||
|
||||
void AVRSPI2DeviceDriver::cs_assert() { |
||||
_cs_assert(); |
||||
} |
||||
|
||||
void AVRSPI2DeviceDriver::cs_release() { |
||||
_cs_release(); |
||||
} |
||||
|
||||
uint8_t AVRSPI2DeviceDriver::transfer(uint8_t data) { |
||||
return _transfer(data); |
||||
} |
||||
|
||||
void AVRSPI2DeviceDriver::transfer(const uint8_t *data, uint16_t len) { |
||||
while (len--) |
||||
_transfer(*data++); |
||||
} |
||||
|
||||
#endif |
@ -1,124 +0,0 @@
@@ -1,124 +0,0 @@
|
||||
/// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*-
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#if (CONFIG_HAL_BOARD == HAL_BOARD_APM1 || CONFIG_HAL_BOARD == HAL_BOARD_APM2) |
||||
|
||||
|
||||
#include <avr/io.h> |
||||
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#include "SPIDevices.h" |
||||
#include "GPIO.h" |
||||
#include "Semaphores.h" |
||||
|
||||
#include "utility/pins_arduino_mega.h" |
||||
|
||||
using namespace AP_HAL_AVR; |
||||
|
||||
#define SPI3_MOSI 14 |
||||
#define SPI3_MISO 15 |
||||
|
||||
extern const AP_HAL::HAL& hal; |
||||
|
||||
AVRSemaphore AVRSPI3DeviceDriver::_semaphore; |
||||
|
||||
void AVRSPI3DeviceDriver::init() { |
||||
/* the spi3 (USART3) sck pin PORTJ2 is not enumerated
|
||||
* by the arduino pin numbers, so we access it directly |
||||
* with AVRDigitalSource. */ |
||||
AVRDigitalSource spi3_sck(_BV(2), PJ); |
||||
spi3_sck.mode(HAL_GPIO_OUTPUT); |
||||
hal.gpio->pinMode(SPI3_MOSI, HAL_GPIO_OUTPUT); |
||||
hal.gpio->pinMode(SPI3_MISO, HAL_GPIO_INPUT); |
||||
|
||||
/* UMSELn1 and UMSELn2: USART in SPI Master mode */ |
||||
UCSR3C = _BV(UMSEL31) | _BV(UMSEL30); |
||||
/* Enable RX and TX. */ |
||||
UCSR3B = _BV(RXEN3) | _BV(TXEN3); |
||||
|
||||
/* Setup chip select pin */ |
||||
_cs_pin->mode(HAL_GPIO_OUTPUT); |
||||
_cs_pin->write(1); |
||||
} |
||||
|
||||
AP_HAL::Semaphore* AVRSPI3DeviceDriver::get_semaphore() { |
||||
return &_semaphore; |
||||
} |
||||
|
||||
void AVRSPI3DeviceDriver::_cs_assert()
|
||||
{ |
||||
/* set the device UCSRnC configuration bits.
|
||||
* only sets data order, clock phase, and clock polarity bits (lowest |
||||
* three bits) */ |
||||
const uint8_t new_ucsr3c = (UCSR3C & ~0x07) | (_ucsr3c & (0x07)); |
||||
UCSR3C = new_ucsr3c; |
||||
/* set the device baud rate */ |
||||
UBRR3 = _ubrr3; |
||||
|
||||
_cs_pin->write(0); |
||||
} |
||||
|
||||
void AVRSPI3DeviceDriver::_cs_release() { |
||||
_cs_pin->write(1); |
||||
} |
||||
|
||||
uint8_t AVRSPI3DeviceDriver::_transfer(uint8_t data) { |
||||
/* Wait for empty transmit buffer */ |
||||
while ( !( UCSR3A & _BV(UDRE3)) ) ; |
||||
|
||||
/* Put data into buffer, sends the data */ |
||||
UDR3 = data; |
||||
|
||||
/* Wait for data to be received */ |
||||
while ( !(UCSR3A & _BV(RXC3)) ) ; |
||||
|
||||
/* Get and return received data from buffer */ |
||||
return UDR3; |
||||
} |
||||
|
||||
void AVRSPI3DeviceDriver::_transfer(const uint8_t *data, uint16_t len) { |
||||
while (len--) { |
||||
/* Wait for empty transmit buffer */ |
||||
while ( !( UCSR3A & _BV(UDRE3)) ) ; |
||||
|
||||
/* Put data into buffer, sends the data */ |
||||
UDR3 = *data++; |
||||
|
||||
/* Wait for data to be received */ |
||||
while ( !(UCSR3A & _BV(RXC3)) ) ; |
||||
|
||||
// dummy read of UDR3 to complete
|
||||
UDR3; |
||||
} |
||||
} |
||||
|
||||
bool AVRSPI3DeviceDriver::transaction(const uint8_t *tx, uint8_t *rx, |
||||
uint16_t len) { |
||||
_cs_assert(); |
||||
if (rx == NULL) { |
||||
_transfer(tx, len); |
||||
} else { |
||||
for (uint16_t i = 0; i < len; i++) { |
||||
rx[i] = _transfer(tx[i]); |
||||
} |
||||
} |
||||
_cs_release(); |
||||
return true; |
||||
} |
||||
|
||||
void AVRSPI3DeviceDriver::cs_assert() { |
||||
_cs_assert(); |
||||
} |
||||
|
||||
void AVRSPI3DeviceDriver::cs_release() { |
||||
_cs_release(); |
||||
} |
||||
|
||||
uint8_t AVRSPI3DeviceDriver::transfer(uint8_t data) { |
||||
return _transfer(data); |
||||
} |
||||
|
||||
void AVRSPI3DeviceDriver::transfer(const uint8_t *data, uint16_t len) { |
||||
_transfer(data, len); |
||||
} |
||||
|
||||
#endif |
@ -1,124 +0,0 @@
@@ -1,124 +0,0 @@
|
||||
|
||||
#ifndef __AP_HAL_AVR_SPI_DEVICES_H__ |
||||
#define __AP_HAL_AVR_SPI_DEVICES_H__ |
||||
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#include "AP_HAL_AVR_Namespace.h" |
||||
|
||||
class AP_HAL_AVR::AVRSPI0DeviceDriver : public AP_HAL::SPIDeviceDriver { |
||||
public: |
||||
AVRSPI0DeviceDriver( |
||||
AP_HAL_AVR::AVRDigitalSource *cs_pin, |
||||
uint8_t spcr_lowspeed, |
||||
uint8_t spcr_highspeed, |
||||
uint8_t spsr |
||||
) : |
||||
_cs_pin(cs_pin), |
||||
_spcr_lowspeed(spcr_lowspeed), |
||||
_spcr_highspeed(spcr_highspeed), |
||||
_spcr(spcr_lowspeed), |
||||
_spsr(spsr) |
||||
{} |
||||
|
||||
void init(); |
||||
AP_HAL::Semaphore* get_semaphore(); |
||||
|
||||
bool transaction(const uint8_t *tx, uint8_t *rx, uint16_t len); |
||||
|
||||
void cs_assert(); |
||||
void cs_release(); |
||||
uint8_t transfer(uint8_t data); |
||||
void transfer(const uint8_t *data, uint16_t len); |
||||
void set_bus_speed(enum bus_speed speed); |
||||
|
||||
private: |
||||
void _cs_assert(); |
||||
void _cs_release(); |
||||
uint8_t _transfer(uint8_t data); |
||||
// used for MPU6k
|
||||
void _transfer16(const uint8_t *tx, uint8_t *rx); |
||||
|
||||
static AP_HAL_AVR::AVRSemaphore _semaphore; |
||||
static bool _force_low_speed; |
||||
|
||||
AP_HAL_AVR::AVRDigitalSource *_cs_pin; |
||||
const uint8_t _spcr_lowspeed; |
||||
const uint8_t _spcr_highspeed; |
||||
uint8_t _spcr; |
||||
const uint8_t _spsr; |
||||
}; |
||||
|
||||
|
||||
class AP_HAL_AVR::AVRSPI2DeviceDriver : public AP_HAL::SPIDeviceDriver { |
||||
public: |
||||
AVRSPI2DeviceDriver( |
||||
AP_HAL_AVR::AVRDigitalSource *cs_pin, |
||||
uint8_t ucsr2c, |
||||
uint16_t ubrr2 |
||||
) : |
||||
_cs_pin(cs_pin), |
||||
_ucsr2c(ucsr2c), |
||||
_ubrr2(ubrr2) |
||||
{} |
||||
|
||||
void init(); |
||||
AP_HAL::Semaphore* get_semaphore(); |
||||
|
||||
bool transaction(const uint8_t *tx, uint8_t *rx, uint16_t len); |
||||
|
||||
void cs_assert(); |
||||
void cs_release(); |
||||
uint8_t transfer(uint8_t data); |
||||
void transfer(const uint8_t *data, uint16_t len); |
||||
|
||||
private: |
||||
void _cs_assert(); |
||||
void _cs_release(); |
||||
uint8_t _transfer(uint8_t data); |
||||
// used for APM1 ADC
|
||||
void _transfer17(const uint8_t *tx, uint8_t *rx); |
||||
|
||||
static AP_HAL_AVR::AVRSemaphore _semaphore; |
||||
|
||||
AP_HAL_AVR::AVRDigitalSource *_cs_pin; |
||||
uint8_t _ucsr2c; |
||||
uint16_t _ubrr2; |
||||
}; |
||||
|
||||
class AP_HAL_AVR::AVRSPI3DeviceDriver : public AP_HAL::SPIDeviceDriver { |
||||
public: |
||||
AVRSPI3DeviceDriver( |
||||
AP_HAL_AVR::AVRDigitalSource *cs_pin, |
||||
uint8_t ucsr3c, |
||||
uint16_t ubrr3 |
||||
) : |
||||
_cs_pin(cs_pin), |
||||
_ucsr3c(ucsr3c), |
||||
_ubrr3(ubrr3) |
||||
{} |
||||
|
||||
void init(); |
||||
AP_HAL::Semaphore* get_semaphore(); |
||||
|
||||
bool transaction(const uint8_t *tx, uint8_t *rx, uint16_t len); |
||||
|
||||
void cs_assert(); |
||||
void cs_release(); |
||||
uint8_t transfer(uint8_t data); |
||||
void transfer(const uint8_t *data, uint16_t len); |
||||
|
||||
private: |
||||
void _cs_assert(); |
||||
void _cs_release(); |
||||
uint8_t _transfer(uint8_t data); |
||||
void _transfer(const uint8_t *data, uint16_t size); |
||||
static AP_HAL_AVR::AVRSemaphore _semaphore; |
||||
|
||||
AP_HAL_AVR::AVRDigitalSource *_cs_pin; |
||||
uint8_t _ucsr3c; |
||||
uint16_t _ubrr3; |
||||
|
||||
}; |
||||
|
||||
|
||||
#endif // __AP_HAL_AVR_SPI_DEVICES_H__
|
@ -1,38 +0,0 @@
@@ -1,38 +0,0 @@
|
||||
|
||||
#ifndef __AP_HAL_AVR_SPI_DRIVER_H__ |
||||
#define __AP_HAL_AVR_SPI_DRIVER_H__ |
||||
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#include "AP_HAL_AVR_Namespace.h" |
||||
#include "GPIO.h" |
||||
#include "SPIDevices.h" |
||||
#include "Semaphores.h" |
||||
|
||||
class AP_HAL_AVR::APM1SPIDeviceManager : public AP_HAL::SPIDeviceManager { |
||||
public: |
||||
void init(void* machtnichts); |
||||
AP_HAL::SPIDeviceDriver* device(enum AP_HAL::SPIDevice d); |
||||
|
||||
private: |
||||
AVRSPI0DeviceDriver* _dataflash; |
||||
AVRSPI0DeviceDriver* _optflow; |
||||
|
||||
AVRSPI2DeviceDriver* _adc; |
||||
}; |
||||
|
||||
class AP_HAL_AVR::APM2SPIDeviceManager : public AP_HAL::SPIDeviceManager { |
||||
public: |
||||
void init(void* machtnichts); |
||||
AP_HAL::SPIDeviceDriver* device(enum AP_HAL::SPIDevice d); |
||||
|
||||
private: |
||||
AVRSPI0DeviceDriver* _mpu6k; |
||||
AVRSPI0DeviceDriver* _ms5611; |
||||
AVRSPI0DeviceDriver* _optflow_spi0; |
||||
|
||||
AVRSPI3DeviceDriver* _dataflash; |
||||
AVRSPI3DeviceDriver* _optflow_spi3; |
||||
}; |
||||
|
||||
#endif // __AP_HAL_AVR_SPI_DRIVER_H__
|
||||
|
@ -1,277 +0,0 @@
@@ -1,277 +0,0 @@
|
||||
/// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#if (CONFIG_HAL_BOARD == HAL_BOARD_APM1 || CONFIG_HAL_BOARD == HAL_BOARD_APM2) |
||||
|
||||
#include <avr/io.h> |
||||
#include <avr/wdt.h> |
||||
#include <avr/interrupt.h> |
||||
|
||||
#include "Scheduler.h" |
||||
#include "utility/ISRRegistry.h" |
||||
#include "memcheck.h" |
||||
using namespace AP_HAL_AVR; |
||||
|
||||
extern const AP_HAL::HAL& hal; |
||||
|
||||
/* AVRScheduler timer interrupt period is controlled by TCNT2.
|
||||
* 256-124 gives a 500Hz period |
||||
* 256-62 gives a 1kHz period. */ |
||||
volatile uint8_t AVRScheduler::_timer2_reset_value = (256 - 62); |
||||
|
||||
/* Static AVRScheduler variables: */ |
||||
AVRTimer AVRScheduler::_timer; |
||||
|
||||
AP_HAL::Proc AVRScheduler::_failsafe = NULL; |
||||
volatile bool AVRScheduler::_timer_suspended = false; |
||||
volatile bool AVRScheduler::_timer_event_missed = false; |
||||
volatile bool AVRScheduler::_in_timer_proc = false; |
||||
AP_HAL::MemberProc AVRScheduler::_timer_proc[AVR_SCHEDULER_MAX_TIMER_PROCS] = {NULL}; |
||||
uint8_t AVRScheduler::_num_timer_procs = 0; |
||||
|
||||
|
||||
AVRScheduler::AVRScheduler() : |
||||
_delay_cb(NULL), |
||||
_min_delay_cb_ms(65535), |
||||
_initialized(false) |
||||
{} |
||||
|
||||
void AVRScheduler::init(void* _isrregistry) { |
||||
ISRRegistry* isrregistry = (ISRRegistry*) _isrregistry; |
||||
|
||||
/* _timer: sets up timer hardware to implement millis & micros. */ |
||||
_timer.init(); |
||||
|
||||
/* TIMER2: Setup the overflow interrupt to occur at 1khz. */ |
||||
TIMSK2 = 0; /* Disable timer interrupt */ |
||||
TCCR2A = 0; /* Normal counting mode */ |
||||
TCCR2B = _BV(CS21) | _BV(CS22); /* Prescaler to clk/256 */ |
||||
TCNT2 = 0; /* Set count to 0 */ |
||||
TIFR2 = _BV(TOV2); /* Clear pending interrupts */ |
||||
TIMSK2 = _BV(TOIE2); /* Enable overflow interrupt*/ |
||||
/* Register _timer_isr_event to trigger on overflow */ |
||||
isrregistry->register_signal(ISR_REGISTRY_TIMER2_OVF, _timer_isr_event);
|
||||
|
||||
/* Turn on global interrupt flag, AVR interupt system will start from this point */ |
||||
sei(); |
||||
|
||||
memcheck_init(); |
||||
} |
||||
|
||||
uint32_t AVRScheduler::micros() { |
||||
return _timer.micros(); |
||||
} |
||||
|
||||
uint32_t AVRScheduler::millis() { |
||||
return _timer.millis(); |
||||
} |
||||
|
||||
/*
|
||||
64 bit version of millis(). This wraps at 32 bits on AVR |
||||
*/ |
||||
uint64_t AVRScheduler::millis64() { |
||||
return millis(); |
||||
} |
||||
|
||||
/*
|
||||
64 bit version of micros(). This wraps when 32 bit millis() wraps |
||||
*/ |
||||
uint64_t AVRScheduler::micros64() { |
||||
// this is slow, but solves the problem with logging uint64_t timestamps
|
||||
uint64_t ret = millis(); |
||||
ret *= 1000ULL; |
||||
ret += micros() % 1000UL; |
||||
return ret; |
||||
} |
||||
|
||||
void AVRScheduler::delay_microseconds(uint16_t us) { |
||||
_timer.delay_microseconds(us); |
||||
} |
||||
|
||||
void AVRScheduler::delay(uint16_t ms) |
||||
{ |
||||
uint32_t start = _timer.micros(); |
||||
|
||||
while (ms > 0) { |
||||
while ((_timer.micros() - start) >= 1000) { |
||||
ms--; |
||||
if (ms == 0) break; |
||||
start += 1000; |
||||
} |
||||
if (_min_delay_cb_ms <= ms) { |
||||
if (_delay_cb) { |
||||
_delay_cb(); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
void AVRScheduler::register_delay_callback(AP_HAL::Proc proc, |
||||
uint16_t min_time_ms) { |
||||
_delay_cb = proc; |
||||
_min_delay_cb_ms = min_time_ms; |
||||
} |
||||
|
||||
void AVRScheduler::register_timer_process(AP_HAL::MemberProc proc)
|
||||
{ |
||||
for (int i = 0; i < _num_timer_procs; i++) { |
||||
if (_timer_proc[i] == proc) { |
||||
return; |
||||
} |
||||
} |
||||
|
||||
if (_num_timer_procs < AVR_SCHEDULER_MAX_TIMER_PROCS) { |
||||
/* this write to _timer_proc can be outside the critical section
|
||||
* because that memory won't be used until _num_timer_procs is |
||||
* incremented. */ |
||||
_timer_proc[_num_timer_procs] = proc; |
||||
/* _num_timer_procs is used from interrupt, and multiple bytes long. */ |
||||
uint8_t sreg = SREG; |
||||
cli(); |
||||
_num_timer_procs++; |
||||
SREG = sreg;
|
||||
} |
||||
|
||||
} |
||||
|
||||
void AVRScheduler::register_io_process(AP_HAL::MemberProc proc)
|
||||
{ |
||||
// IO processes not supported on AVR
|
||||
} |
||||
|
||||
void AVRScheduler::register_timer_failsafe(AP_HAL::Proc failsafe, uint32_t period_us) { |
||||
/* XXX Assert period_us == 1000 */ |
||||
_failsafe = failsafe; |
||||
} |
||||
|
||||
void AVRScheduler::suspend_timer_procs() { |
||||
_timer_suspended = true; |
||||
} |
||||
|
||||
void AVRScheduler::resume_timer_procs() { |
||||
_timer_suspended = false; |
||||
if (_timer_event_missed == true) { |
||||
_run_timer_procs(false); |
||||
_timer_event_missed = false; |
||||
} |
||||
} |
||||
|
||||
bool AVRScheduler::in_timerprocess() { |
||||
return _in_timer_proc; |
||||
} |
||||
|
||||
void AVRScheduler::_timer_isr_event() { |
||||
// we enable the interrupt again immediately and also enable
|
||||
// interrupts. This allows other time critical interrupts to
|
||||
// run (such as the serial receive interrupt). We catch the
|
||||
// timer calls taking too long using _in_timer_call.
|
||||
// This approach also gives us a nice uniform spacing between
|
||||
// timer calls
|
||||
|
||||
TCNT2 = _timer2_reset_value; |
||||
sei(); |
||||
_run_timer_procs(true); |
||||
} |
||||
|
||||
void AVRScheduler::_run_timer_procs(bool called_from_isr) { |
||||
|
||||
if (_in_timer_proc) { |
||||
// the timer calls took longer than the period of the
|
||||
// timer. This is bad, and may indicate a serious
|
||||
// driver failure. We can't just call the drivers
|
||||
// again, as we could run out of stack. So we only
|
||||
// call the _failsafe call. It's job is to detect if
|
||||
// the drivers or the main loop are indeed dead and to
|
||||
// activate whatever failsafe it thinks may help if
|
||||
// need be. We assume the failsafe code can't
|
||||
// block. If it does then we will recurse and die when
|
||||
// we run out of stack
|
||||
if (_failsafe != NULL) { |
||||
_failsafe(); |
||||
} |
||||
return; |
||||
} |
||||
|
||||
_in_timer_proc = true; |
||||
|
||||
if (!_timer_suspended) { |
||||
// now call the timer based drivers
|
||||
for (int i = 0; i < _num_timer_procs; i++) { |
||||
if (_timer_proc[i]) { |
||||
_timer_proc[i](); |
||||
} |
||||
} |
||||
} else if (called_from_isr) { |
||||
_timer_event_missed = true; |
||||
} |
||||
|
||||
// and the failsafe, if one is setup
|
||||
if (_failsafe != NULL) { |
||||
_failsafe(); |
||||
} |
||||
|
||||
_in_timer_proc = false; |
||||
} |
||||
|
||||
bool AVRScheduler::system_initializing() { |
||||
return !_initialized; |
||||
} |
||||
|
||||
void AVRScheduler::system_initialized() { |
||||
if (_initialized) { |
||||
panic(PSTR("PANIC: scheduler::system_initialized called" |
||||
"more than once")); |
||||
} |
||||
_initialized = true; |
||||
} |
||||
|
||||
void AVRScheduler::panic(const prog_char_t* errormsg, ...) { |
||||
/* Suspend timer processes. We still want the timer event to go off
|
||||
* to run the _failsafe code, however. */ |
||||
_timer_suspended = true; |
||||
/* Print the error message on both ports */ |
||||
hal.uartA->println_P(errormsg); |
||||
hal.uartC->println_P(errormsg); |
||||
/* Spin forever. */ |
||||
for(;;); |
||||
} |
||||
|
||||
void AVRScheduler::reboot(bool hold_in_bootloader) { |
||||
hal.uartA->println_P(PSTR("GOING DOWN FOR A REBOOT\r\n")); |
||||
hal.scheduler->delay(100); |
||||
#if CONFIG_HAL_BOARD == HAL_BOARD_APM2 |
||||
/* The APM2 bootloader will reset the watchdog shortly after
|
||||
* starting, so we can use the watchdog to force a reboot |
||||
*/ |
||||
cli(); |
||||
wdt_enable(WDTO_15MS); |
||||
for(;;); |
||||
#else |
||||
cli(); |
||||
/* Making a null pointer call will cause all AVRs to reboot
|
||||
* but they may not come back alive properly - we need to setup |
||||
* the IO the way the bootloader would. |
||||
*/ |
||||
void (*fn)(void) = NULL; |
||||
fn(); |
||||
for(;;); |
||||
#endif |
||||
|
||||
} |
||||
|
||||
/**
|
||||
set timer speed in Hz. Used by ArduCopter on APM2 to reduce the |
||||
cost of timer interrupts |
||||
*/ |
||||
void AVRScheduler::set_timer_speed(uint16_t timer_hz) |
||||
{ |
||||
if (timer_hz > 1000) { |
||||
timer_hz = 1000; |
||||
} |
||||
if (timer_hz < 250) { |
||||
timer_hz = 250; |
||||
} |
||||
_timer2_reset_value = 256 - (62 * (1000 / timer_hz)); |
||||
} |
||||
|
||||
#endif |
@ -1,77 +0,0 @@
@@ -1,77 +0,0 @@
|
||||
|
||||
#ifndef __AP_HAL_AVR_SCHEDULER_H__ |
||||
#define __AP_HAL_AVR_SCHEDULER_H__ |
||||
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#include "AP_HAL_AVR_Namespace.h" |
||||
|
||||
#define AVR_SCHEDULER_MAX_TIMER_PROCS 4 |
||||
|
||||
/* Class for managing the AVR Timers: */ |
||||
class AP_HAL_AVR::AVRTimer { |
||||
public: |
||||
static void init(); |
||||
static uint32_t millis(); |
||||
static uint32_t micros(); |
||||
static void delay_microseconds(uint16_t us); |
||||
}; |
||||
|
||||
/* Scheduler implementation: */ |
||||
class AP_HAL_AVR::AVRScheduler : public AP_HAL::Scheduler { |
||||
public: |
||||
AVRScheduler(); |
||||
/* AP_HAL::Scheduler methods */ |
||||
|
||||
/* init: implementation-specific void* argument expected to be an
|
||||
* AP_HAL_AVR::ISRRegistry*. */ |
||||
void init(void *isrregistry); |
||||
void delay(uint16_t ms); |
||||
uint32_t millis(); |
||||
uint32_t micros(); |
||||
uint64_t millis64(); |
||||
uint64_t micros64(); |
||||
void delay_microseconds(uint16_t us); |
||||
void register_delay_callback(AP_HAL::Proc, uint16_t min_time_ms); |
||||
|
||||
void register_timer_process(AP_HAL::MemberProc); |
||||
void register_io_process(AP_HAL::MemberProc); |
||||
void suspend_timer_procs(); |
||||
void resume_timer_procs(); |
||||
|
||||
bool in_timerprocess(); |
||||
|
||||
void register_timer_failsafe(AP_HAL::Proc, uint32_t period_us); |
||||
|
||||
bool system_initializing(); |
||||
void system_initialized(); |
||||
|
||||
void panic(const prog_char_t *errormsg, ...) FORMAT(2, 3) NORETURN; |
||||
void reboot(bool hold_in_bootloader); |
||||
|
||||
void set_timer_speed(uint16_t timer_hz); |
||||
|
||||
private: |
||||
static AVRTimer _timer; |
||||
|
||||
static volatile bool _in_timer_proc; |
||||
|
||||
AP_HAL::Proc _delay_cb; |
||||
uint16_t _min_delay_cb_ms; |
||||
bool _initialized; |
||||
|
||||
/* _timer_isr_event() and _run_timer_procs are static so they can be
|
||||
* called from an interrupt. */ |
||||
static void _timer_isr_event(); |
||||
static void _run_timer_procs(bool called_from_isr); |
||||
|
||||
static AP_HAL::Proc _failsafe; |
||||
|
||||
static volatile bool _timer_suspended; |
||||
static volatile bool _timer_event_missed; |
||||
static AP_HAL::MemberProc _timer_proc[AVR_SCHEDULER_MAX_TIMER_PROCS]; |
||||
static uint8_t _num_timer_procs; |
||||
static volatile uint8_t _timer2_reset_value; |
||||
|
||||
}; |
||||
#endif // __AP_HAL_AVR_SCHEDULER_H__
|
||||
|
@ -1,157 +0,0 @@
@@ -1,157 +0,0 @@
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#if (CONFIG_HAL_BOARD == HAL_BOARD_APM1 || CONFIG_HAL_BOARD == HAL_BOARD_APM2) |
||||
|
||||
#include <avr/io.h> |
||||
#include <avr/interrupt.h> |
||||
|
||||
#include "Scheduler.h" |
||||
using namespace AP_HAL_AVR; |
||||
|
||||
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) |
||||
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) |
||||
|
||||
#if (CONFIG_HAL_BOARD == HAL_BOARD_APM1 ) |
||||
#define AVR_TIMER_OVF_VECT TIMER4_OVF_vect |
||||
#define AVR_TIMER_TCNT TCNT4 |
||||
#define AVR_TIMER_TIFR TIFR4 |
||||
#define AVR_TIMER_TCCRA TCCR4A |
||||
#define AVR_TIMER_TCCRB TCCR4B |
||||
#define AVR_TIMER_OCRA OCR4A |
||||
#define AVR_TIMER_TIMSK TIMSK4 |
||||
#define AVR_TIMER_TOIE TOIE4 |
||||
#define AVR_TIMER_WGM0 WGM40 |
||||
#define AVR_TIMER_WGM1 WGM41 |
||||
#define AVR_TIMER_WGM2 WGM42 |
||||
#define AVR_TIMER_WGM3 WGM43 |
||||
#define AVR_TIMER_CS1 CS41 |
||||
|
||||
|
||||
#elif (CONFIG_HAL_BOARD == HAL_BOARD_APM2 ) |
||||
#define AVR_TIMER_OVF_VECT TIMER5_OVF_vect |
||||
#define AVR_TIMER_TCNT TCNT5 |
||||
#define AVR_TIMER_TIFR TIFR5 |
||||
#define AVR_TIMER_TCCRA TCCR5A |
||||
#define AVR_TIMER_TCCRB TCCR5B |
||||
#define AVR_TIMER_OCRA OCR5A |
||||
#define AVR_TIMER_TIMSK TIMSK5 |
||||
#define AVR_TIMER_TOIE TOIE5 |
||||
#define AVR_TIMER_WGM0 WGM50 |
||||
#define AVR_TIMER_WGM1 WGM51 |
||||
#define AVR_TIMER_WGM2 WGM52 |
||||
#define AVR_TIMER_WGM3 WGM53 |
||||
#define AVR_TIMER_CS1 CS51 |
||||
|
||||
#endif |
||||
|
||||
static volatile uint32_t timer_micros_counter = 0; |
||||
static volatile uint32_t timer_millis_counter = 0; |
||||
|
||||
void AVRTimer::init() { |
||||
uint8_t oldSREG = SREG; |
||||
cli(); |
||||
|
||||
// Timer cleanup before configuring
|
||||
AVR_TIMER_TCNT = 0; |
||||
AVR_TIMER_TIFR = 0; |
||||
|
||||
// Set timer 8x prescaler fast PWM mode toggle compare at OCRA
|
||||
AVR_TIMER_TCCRA = _BV( AVR_TIMER_WGM0 ) | _BV( AVR_TIMER_WGM1 ); |
||||
AVR_TIMER_TCCRB |= _BV( AVR_TIMER_WGM3 ) | _BV( AVR_TIMER_WGM2 ) | _BV( AVR_TIMER_CS1 ); |
||||
AVR_TIMER_OCRA = 40000 - 1; // -1 to correct for wrap
|
||||
|
||||
// Enable overflow interrupt
|
||||
AVR_TIMER_TIMSK |= _BV( AVR_TIMER_TOIE ); |
||||
|
||||
// set a2d prescale factor to 128
|
||||
// 16 MHz / 128 = 125 KHz, inside the desired 50-200 KHz range.
|
||||
// XXX: this will not work properly for other clock speeds, and
|
||||
// this code should use F_CPU to determine the prescale factor.
|
||||
sbi(ADCSRA, ADPS2); |
||||
sbi(ADCSRA, ADPS1); |
||||
sbi(ADCSRA, ADPS0); |
||||
|
||||
// enable a2d conversions
|
||||
sbi(ADCSRA, ADEN); |
||||
|
||||
// the bootloader connects pins 0 and 1 to the USART; disconnect them
|
||||
// here so they can be used as normal digital i/o; they will be
|
||||
// reconnected in Serial.begin()
|
||||
UCSR0B = 0; |
||||
|
||||
SREG = oldSREG; |
||||
} |
||||
|
||||
SIGNAL( AVR_TIMER_OVF_VECT) |
||||
{ |
||||
// Hardcoded for AVR@16MHZ and 8x pre-scale 16-bit timer overflow at 40000
|
||||
timer_micros_counter += 40000 / 2; // 20000us each overflow
|
||||
timer_millis_counter += 40000 / 2000; // 20ms each overlflow
|
||||
} |
||||
|
||||
uint32_t AVRTimer::micros() { |
||||
uint8_t oldSREG = SREG; |
||||
cli(); |
||||
|
||||
// Hardcoded for AVR@16MHZ and 8x pre-scale 16-bit timer
|
||||
//uint32_t time_micros = timer_micros_counter + (AVR_TIMER_TCNT / 2);
|
||||
//uint32_t time_micros = timer_micros_counter + (AVR_TIMER_TCNT >> 1);
|
||||
|
||||
uint32_t time_micros = timer_micros_counter; |
||||
uint16_t tcnt = AVR_TIMER_TCNT; |
||||
|
||||
// Check for imminent timer overflow interrupt and pre-increment counter
|
||||
if ( AVR_TIMER_TIFR & 1 && tcnt < 39999 ) |
||||
{ |
||||
time_micros += 40000 / 2; |
||||
} |
||||
SREG = oldSREG; |
||||
|
||||
return time_micros + (tcnt >> 1); |
||||
} |
||||
|
||||
uint32_t AVRTimer::millis() { |
||||
uint8_t oldSREG = SREG; |
||||
cli(); |
||||
// Hardcoded for AVR@16MHZ and 8x pre-scale 16-bit timer
|
||||
//uint32_t time_millis = timer_millis_counter + (AVR_TIMER_TCNT / 2000) ;
|
||||
//uint32_t time_millis = timer_millis_counter + (AVR_TIMER_TCNT >> 11); // AVR_TIMER_CNT / 2048 is close enough (24us counter delay)
|
||||
|
||||
uint32_t time_millis = timer_millis_counter; |
||||
uint16_t tcnt = AVR_TIMER_TCNT; |
||||
|
||||
// Check for imminent timer overflow interrupt and pre-increment counter
|
||||
if ( AVR_TIMER_TIFR & 1 && tcnt < 39999 ) |
||||
{ |
||||
time_millis += 40000 / 2000; |
||||
} |
||||
SREG = oldSREG; |
||||
|
||||
return time_millis + (tcnt >> 11); |
||||
} |
||||
|
||||
|
||||
/* Delay for the given number of microseconds. Assumes a 16 MHz clock. */ |
||||
void AVRTimer::delay_microseconds(uint16_t us) |
||||
{ |
||||
// for the 16 MHz clock on most Arduino boards
|
||||
// for a one-microsecond delay, simply return. the overhead
|
||||
// of the function call yields a delay of approximately 1 1/8 us.
|
||||
if (--us == 0) |
||||
return; |
||||
|
||||
// the following loop takes a quarter of a microsecond (4 cycles)
|
||||
// per iteration, so execute it four times for each microsecond of
|
||||
// delay requested.
|
||||
us <<= 2; |
||||
|
||||
// account for the time taken in the preceeding commands.
|
||||
us -= 2; |
||||
|
||||
// busy wait
|
||||
__asm__ __volatile__ ( |
||||
"1: sbiw %0,1" "\n\t" // 2 cycles
|
||||
"brne 1b" : "=w" (us) : "0" (us) // 2 cycles
|
||||
); |
||||
} |
||||
|
||||
#endif |
@ -1,80 +0,0 @@
@@ -1,80 +0,0 @@
|
||||
/// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*-
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
|
||||
#if (CONFIG_HAL_BOARD == HAL_BOARD_APM1 || CONFIG_HAL_BOARD == HAL_BOARD_APM2) |
||||
|
||||
#include <avr/io.h> |
||||
#include <avr/interrupt.h> |
||||
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#include "AP_HAL_AVR.h" |
||||
#include "Semaphores.h" |
||||
#include "Scheduler.h" |
||||
using namespace AP_HAL_AVR; |
||||
|
||||
extern const AP_HAL::HAL& hal; |
||||
|
||||
// Constructor
|
||||
AVRSemaphore::AVRSemaphore() : _taken(false) {} |
||||
|
||||
bool AVRSemaphore::give() { |
||||
if (!_taken) { |
||||
return false; |
||||
} else { |
||||
_taken = false; |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
bool AVRSemaphore::take(uint32_t timeout_ms) { |
||||
if (hal.scheduler->in_timerprocess()) { |
||||
hal.scheduler->panic(PSTR("PANIC: AVRSemaphore::take used from " |
||||
"inside timer process")); |
||||
return false; /* Never reached - panic does not return */ |
||||
} |
||||
return _take_from_mainloop(timeout_ms); |
||||
} |
||||
|
||||
bool AVRSemaphore::take_nonblocking() { |
||||
if (hal.scheduler->in_timerprocess()) { |
||||
return _take_nonblocking(); |
||||
} else { |
||||
return _take_from_mainloop(0); |
||||
} |
||||
} |
||||
|
||||
bool AVRSemaphore::_take_from_mainloop(uint32_t timeout_ms) { |
||||
/* Try to take immediately */ |
||||
if (_take_nonblocking()) { |
||||
return true; |
||||
} else if (timeout_ms == 0) { |
||||
/* Return immediately if timeout is 0 */ |
||||
return false; |
||||
} |
||||
|
||||
uint16_t timeout_ticks = timeout_ms*10; |
||||
do { |
||||
/* Delay 1ms until we can successfully take, or we timed out */ |
||||
hal.scheduler->delay_microseconds(100); |
||||
timeout_ticks--; |
||||
if (_take_nonblocking()) { |
||||
return true; |
||||
} |
||||
} while (timeout_ticks > 0); |
||||
|
||||
return false; |
||||
} |
||||
|
||||
bool AVRSemaphore::_take_nonblocking() { |
||||
bool result = false; |
||||
uint8_t sreg = SREG; |
||||
cli(); |
||||
if (!_taken) { |
||||
_taken = true; |
||||
result = true; |
||||
} |
||||
SREG = sreg; |
||||
return result; |
||||
} |
||||
|
||||
#endif // CONFIG_HAL_BOARD
|
@ -1,23 +0,0 @@
@@ -1,23 +0,0 @@
|
||||
|
||||
#ifndef __AP_HAL_AVR_SEMAPHORES_H__ |
||||
#define __AP_HAL_AVR_SEMAPHORES_H__ |
||||
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#include "AP_HAL_AVR_Namespace.h" |
||||
|
||||
class AP_HAL_AVR::AVRSemaphore : public AP_HAL::Semaphore { |
||||
public: |
||||
AVRSemaphore(); |
||||
|
||||
bool give(); |
||||
bool take(uint32_t timeout_ms); |
||||
bool take_nonblocking(); |
||||
|
||||
protected: |
||||
bool _take_from_mainloop(uint32_t timeout_ms); |
||||
bool _take_nonblocking(); |
||||
|
||||
volatile bool _taken; |
||||
}; |
||||
|
||||
#endif // __AP_HAL_AVR_SEMAPHORES_H__
|
@ -1,31 +0,0 @@
@@ -1,31 +0,0 @@
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#if (CONFIG_HAL_BOARD == HAL_BOARD_APM1 || CONFIG_HAL_BOARD == HAL_BOARD_APM2) |
||||
|
||||
#include <avr/io.h> |
||||
#include <avr/eeprom.h> |
||||
#include "Storage.h" |
||||
using namespace AP_HAL_AVR; |
||||
|
||||
void AVREEPROMStorage::read_block(void *dst, uint16_t src, size_t n)
|
||||
{ |
||||
eeprom_read_block(dst,(const void*)src,n); |
||||
} |
||||
|
||||
void AVREEPROMStorage::write_block(uint16_t dst, const void *src, size_t n)
|
||||
{ |
||||
uint8_t *p = (uint8_t *)src; |
||||
while (n--) { |
||||
/*
|
||||
it is much faster to read than write, so it is worth |
||||
checking if the value is already correct |
||||
*/ |
||||
uint8_t b = eeprom_read_byte((uint8_t*)dst); |
||||
if (b != *p) { |
||||
eeprom_write_byte((uint8_t*)dst, *p); |
||||
} |
||||
dst++; |
||||
p++; |
||||
} |
||||
} |
||||
|
||||
#endif |
@ -1,17 +0,0 @@
@@ -1,17 +0,0 @@
|
||||
|
||||
|
||||
#ifndef __AP_HAL_AVR_STORAGE_H__ |
||||
#define __AP_HAL_AVR_STORAGE_H__ |
||||
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#include "AP_HAL_AVR_Namespace.h" |
||||
|
||||
class AP_HAL_AVR::AVREEPROMStorage : public AP_HAL::Storage { |
||||
public: |
||||
AVREEPROMStorage() {} |
||||
void init(void* machtnichts) {} |
||||
void read_block(void *dst, uint16_t src, size_t n); |
||||
void write_block(uint16_t dst, const void* src, size_t n); |
||||
}; |
||||
|
||||
#endif // __AP_HAL_AVR_STORAGE_H__
|
@ -1,313 +0,0 @@
@@ -1,313 +0,0 @@
|
||||
// -*- Mode: C++; c-basic-offset: 8; indent-tabs-mode: nil -*-
|
||||
/*
|
||||
This program is free software: you can redistribute it and/or modify |
||||
it under the terms of the GNU General Public License as published by |
||||
the Free Software Foundation, either version 3 of the License, or |
||||
(at your option) any later version. |
||||
|
||||
This program is distributed in the hope that it will be useful, |
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
GNU General Public License for more details. |
||||
|
||||
You should have received a copy of the GNU General Public License |
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
|
||||
//
|
||||
// Copyright (c) 2010 Michael Smith. All rights reserved.
|
||||
//
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#if (CONFIG_HAL_BOARD == HAL_BOARD_APM1 || CONFIG_HAL_BOARD == HAL_BOARD_APM2) |
||||
|
||||
#include <limits.h> |
||||
#include <stdlib.h> |
||||
#include <stdarg.h> |
||||
|
||||
#include <avr/pgmspace.h> |
||||
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#include <AP_Math/AP_Math.h> |
||||
#include "UARTDriver.h" |
||||
|
||||
using namespace AP_HAL_AVR; |
||||
|
||||
#define FS_MAX_PORTS 4 |
||||
AVRUARTDriver::Buffer __AVRUARTDriver__rxBuffer[FS_MAX_PORTS]; |
||||
AVRUARTDriver::Buffer __AVRUARTDriver__txBuffer[FS_MAX_PORTS]; |
||||
|
||||
AVRUARTDriver::AVRUARTDriver( |
||||
const uint8_t portNumber, volatile uint8_t *ubrrh, |
||||
volatile uint8_t *ubrrl, volatile uint8_t *ucsra, |
||||
volatile uint8_t *ucsrb, const uint8_t u2x, |
||||
const uint8_t portEnableBits, const uint8_t portTxBits) : |
||||
_ubrrh(ubrrh), |
||||
_ubrrl(ubrrl), |
||||
_ucsra(ucsra), |
||||
_ucsrb(ucsrb), |
||||
_u2x(u2x), |
||||
_portEnableBits(portEnableBits), |
||||
_portTxBits(portTxBits), |
||||
_rxBuffer(&__AVRUARTDriver__rxBuffer[portNumber]), |
||||
_txBuffer(&__AVRUARTDriver__txBuffer[portNumber]) |
||||
{ |
||||
_initialized = true; |
||||
begin(57600); |
||||
} |
||||
/* UARTDriver method implementations */ |
||||
|
||||
void AVRUARTDriver::begin(uint32_t baud, uint16_t rxSpace, uint16_t txSpace) { |
||||
uint16_t ubrr; |
||||
bool use_u2x = true; |
||||
bool need_allocate = true; |
||||
|
||||
// if we are currently open...
|
||||
if (_open) { |
||||
// If the caller wants to preserve the buffer sizing, work out what
|
||||
// it currently is...
|
||||
if (0 == rxSpace) |
||||
rxSpace = _rxBuffer->mask + 1; |
||||
if (0 == txSpace) |
||||
txSpace = _txBuffer->mask + 1; |
||||
|
||||
if (rxSpace == (_rxBuffer->mask + 1U) &&
|
||||
txSpace == (_txBuffer->mask + 1U)) { |
||||
// avoid re-allocating the buffers if possible
|
||||
need_allocate = false; |
||||
*_ucsrb &= ~(_portEnableBits | _portTxBits); |
||||
} else { |
||||
// close the port in its current configuration, clears _open
|
||||
end(); |
||||
} |
||||
} |
||||
|
||||
if (need_allocate) { |
||||
// allocate buffers
|
||||
if (!_allocBuffer(_rxBuffer, rxSpace ? : _default_rx_buffer_size) |
||||
|| !_allocBuffer(_txBuffer, txSpace ? : _default_tx_buffer_size)) { |
||||
end(); |
||||
return; // couldn't allocate buffers - fatal
|
||||
} |
||||
} |
||||
|
||||
// reset buffer pointers
|
||||
_txBuffer->head = _txBuffer->tail = 0; |
||||
_rxBuffer->head = _rxBuffer->tail = 0; |
||||
|
||||
// mark the port as open
|
||||
_open = true; |
||||
|
||||
// If the user has supplied a new baud rate, compute the new UBRR value.
|
||||
if (baud > 0) { |
||||
#if F_CPU == 16000000UL |
||||
// hardcoded exception for compatibility with the bootloader shipped
|
||||
// with the Duemilanove and previous boards and the firmware on the 8U2
|
||||
// on the Uno and Mega 2560.
|
||||
if (baud == 57600) |
||||
use_u2x = false; |
||||
#endif |
||||
|
||||
if (use_u2x) { |
||||
*_ucsra = 1 << _u2x; |
||||
ubrr = (F_CPU / 4 / baud - 1) / 2; |
||||
} else { |
||||
*_ucsra = 0; |
||||
ubrr = (F_CPU / 8 / baud - 1) / 2; |
||||
} |
||||
|
||||
*_ubrrh = ubrr >> 8; |
||||
*_ubrrl = ubrr; |
||||
} |
||||
|
||||
*_ucsrb |= _portEnableBits; |
||||
|
||||
} |
||||
|
||||
void AVRUARTDriver::end() { |
||||
*_ucsrb &= ~(_portEnableBits | _portTxBits); |
||||
|
||||
_freeBuffer(_rxBuffer); |
||||
_freeBuffer(_txBuffer); |
||||
_open = false; |
||||
} |
||||
|
||||
int16_t AVRUARTDriver::available(void) { |
||||
if (!_open) |
||||
return (-1); |
||||
return ((_rxBuffer->head - _rxBuffer->tail) & _rxBuffer->mask); |
||||
} |
||||
|
||||
|
||||
|
||||
int16_t AVRUARTDriver::txspace(void) { |
||||
if (!_open) |
||||
return (-1); |
||||
return ((_txBuffer->mask+1) - ((_txBuffer->head - _txBuffer->tail) & _txBuffer->mask)); |
||||
} |
||||
|
||||
int16_t AVRUARTDriver::read(void) { |
||||
uint8_t c; |
||||
|
||||
// if the head and tail are equal, the buffer is empty
|
||||
if (!_open || (_rxBuffer->head == _rxBuffer->tail)) |
||||
return (-1); |
||||
|
||||
// pull character from tail
|
||||
c = _rxBuffer->bytes[_rxBuffer->tail]; |
||||
_rxBuffer->tail = (_rxBuffer->tail + 1) & _rxBuffer->mask; |
||||
|
||||
return (c); |
||||
} |
||||
|
||||
void AVRUARTDriver::flush(void) { |
||||
// don't reverse this or there may be problems if the RX interrupt
|
||||
// occurs after reading the value of _rxBuffer->head but before writing
|
||||
// the value to _rxBuffer->tail; the previous value of head
|
||||
// may be written to tail, making it appear as if the buffer
|
||||
// don't reverse this or there may be problems if the RX interrupt
|
||||
// occurs after reading the value of head but before writing
|
||||
// the value to tail; the previous value of rx_buffer_head
|
||||
// may be written to tail, making it appear as if the buffer
|
||||
// were full, not empty.
|
||||
_rxBuffer->head = _rxBuffer->tail; |
||||
|
||||
// don't reverse this or there may be problems if the TX interrupt
|
||||
// occurs after reading the value of _txBuffer->tail but before writing
|
||||
// the value to _txBuffer->head.
|
||||
_txBuffer->tail = _txBuffer->head; |
||||
} |
||||
|
||||
size_t AVRUARTDriver::write(uint8_t c) { |
||||
uint8_t i; |
||||
|
||||
if (!_open) // drop bytes if not open
|
||||
return 0; |
||||
|
||||
// wait for room in the tx buffer
|
||||
i = (_txBuffer->head + 1) & _txBuffer->mask; |
||||
|
||||
// if the port is set into non-blocking mode, then drop the byte
|
||||
// if there isn't enough room for it in the transmit buffer
|
||||
if (_nonblocking_writes && i == _txBuffer->tail) { |
||||
return 0; |
||||
} |
||||
|
||||
while (i == _txBuffer->tail) |
||||
; |
||||
|
||||
// add byte to the buffer
|
||||
_txBuffer->bytes[_txBuffer->head] = c; |
||||
_txBuffer->head = i; |
||||
|
||||
// enable the data-ready interrupt, as it may be off if the buffer is empty
|
||||
*_ucsrb |= _portTxBits; |
||||
|
||||
// return number of bytes written (always 1)
|
||||
return 1; |
||||
} |
||||
|
||||
/*
|
||||
write size bytes to the write buffer |
||||
*/ |
||||
size_t AVRUARTDriver::write(const uint8_t *buffer, size_t size) |
||||
{ |
||||
if (!_open) { |
||||
return 0; |
||||
} |
||||
|
||||
if (!_nonblocking_writes) { |
||||
/*
|
||||
use the per-byte delay loop in write() above for blocking writes |
||||
*/ |
||||
size_t ret = 0; |
||||
while (size--) { |
||||
if (write(*buffer++) != 1) break; |
||||
ret++; |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
int16_t space = txspace(); |
||||
if (space <= 0) { |
||||
return 0; |
||||
} |
||||
if (size > (size_t)space) { |
||||
// throw away remainder if too much data
|
||||
size = space; |
||||
} |
||||
if (_txBuffer->tail > _txBuffer->head) { |
||||
// perform as single memcpy
|
||||
memcpy(&_txBuffer->bytes[_txBuffer->head], buffer, size); |
||||
_txBuffer->head = (_txBuffer->head + size) & _txBuffer->mask; |
||||
// enable the data-ready interrupt, as it may be off if the buffer is empty
|
||||
*_ucsrb |= _portTxBits; |
||||
return size; |
||||
} |
||||
|
||||
// perform as two memcpy calls
|
||||
uint16_t n = (_txBuffer->mask+1) - _txBuffer->head; |
||||
if (n > size) n = size; |
||||
memcpy(&_txBuffer->bytes[_txBuffer->head], buffer, n); |
||||
_txBuffer->head = (_txBuffer->head + n) & _txBuffer->mask; |
||||
buffer += n; |
||||
n = size - n; |
||||
if (n > 0) { |
||||
memcpy(&_txBuffer->bytes[0], buffer, n); |
||||
_txBuffer->head = (_txBuffer->head + n) & _txBuffer->mask; |
||||
}
|
||||
|
||||
// enable the data-ready interrupt, as it may be off if the buffer is empty
|
||||
*_ucsrb |= _portTxBits; |
||||
return size; |
||||
} |
||||
|
||||
// Buffer management ///////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
bool AVRUARTDriver::_allocBuffer(Buffer *buffer, uint16_t size) |
||||
{ |
||||
uint8_t mask; |
||||
uint8_t shift; |
||||
|
||||
// init buffer state
|
||||
buffer->head = buffer->tail = 0; |
||||
|
||||
// Compute the power of 2 greater or equal to the requested buffer size
|
||||
// and then a mask to simplify wrapping operations. Using __builtin_clz
|
||||
// would seem to make sense, but it uses a 256(!) byte table.
|
||||
// Note that we ignore requests for more than BUFFER_MAX space.
|
||||
for (shift = 1; (1U << shift) < min(_max_buffer_size, size); shift++) |
||||
; |
||||
mask = (1U << shift) - 1; |
||||
|
||||
// If the descriptor already has a buffer allocated we need to take
|
||||
// care of it.
|
||||
if (buffer->bytes) { |
||||
|
||||
// If the allocated buffer is already the correct size then
|
||||
// we have nothing to do
|
||||
if (buffer->mask == mask) |
||||
return true; |
||||
|
||||
// Dispose of the old buffer.
|
||||
free(buffer->bytes); |
||||
} |
||||
buffer->mask = mask; |
||||
|
||||
// allocate memory for the buffer - if this fails, we fail.
|
||||
buffer->bytes = (uint8_t *) malloc(buffer->mask + (size_t)1); |
||||
|
||||
return (buffer->bytes != NULL); |
||||
} |
||||
|
||||
void AVRUARTDriver::_freeBuffer(Buffer *buffer) |
||||
{ |
||||
buffer->head = buffer->tail = 0; |
||||
buffer->mask = 0; |
||||
if (NULL != buffer->bytes) { |
||||
free(buffer->bytes); |
||||
buffer->bytes = NULL; |
||||
} |
||||
} |
||||
|
||||
#endif |
@ -1,208 +0,0 @@
@@ -1,208 +0,0 @@
|
||||
|
||||
#ifndef __AP_HAL_AVR_UART_DRIVER_H__ |
||||
#define __AP_HAL_AVR_UART_DRIVER_H__ |
||||
#include <AP_HAL/AP_HAL_Boards.h> |
||||
#if (CONFIG_HAL_BOARD == HAL_BOARD_APM1 || CONFIG_HAL_BOARD == HAL_BOARD_APM2) |
||||
|
||||
#include <stdint.h> |
||||
#include <stdarg.h> |
||||
|
||||
#include <avr/interrupt.h> |
||||
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#include "AP_HAL_AVR_Namespace.h" |
||||
|
||||
/**
|
||||
* AVRUARTDriver is an implementation of UARTDriver for the AVR. |
||||
* It will be a thin wrapper on FastSerial. |
||||
*/ |
||||
|
||||
class AP_HAL_AVR::AVRUARTDriver : public AP_HAL::UARTDriver { |
||||
public: |
||||
AVRUARTDriver( |
||||
const uint8_t portNumber, volatile uint8_t *ubrrh, |
||||
volatile uint8_t *ubrrl, volatile uint8_t *ucsra, |
||||
volatile uint8_t *ucsrb, const uint8_t u2x, |
||||
const uint8_t portEnableBits, const uint8_t portTxBits); |
||||
|
||||
/* Implementations of UARTDriver virtual methods */ |
||||
void begin(uint32_t b) { begin(b, 0, 0); } |
||||
void begin(uint32_t b, uint16_t rxS, uint16_t txS); |
||||
void end(); |
||||
void flush(); |
||||
bool is_initialized() { return _initialized; } |
||||
|
||||
void set_blocking_writes(bool blocking) { |
||||
_nonblocking_writes = !blocking; |
||||
} |
||||
|
||||
bool tx_pending() { |
||||
return (_txBuffer->head != _txBuffer->tail); |
||||
} |
||||
|
||||
/* Implementations of Stream virtual methods */ |
||||
int16_t available(); |
||||
int16_t txspace(); |
||||
int16_t read(); |
||||
|
||||
/* Implementations of Print virtual methods */ |
||||
size_t write(uint8_t c); |
||||
size_t write(const uint8_t *buffer, size_t size); |
||||
|
||||
/// Transmit/receive buffer descriptor.
|
||||
///
|
||||
/// Public so the interrupt handlers can see it
|
||||
struct Buffer { |
||||
volatile uint8_t head, tail; ///< head and tail pointers
|
||||
uint8_t mask; ///< buffer size mask for pointer wrap
|
||||
uint8_t *bytes; ///< pointer to allocated buffer
|
||||
}; |
||||
private: |
||||
/* Instance Variables */ |
||||
bool _initialized; |
||||
|
||||
// register accessors
|
||||
volatile uint8_t * const _ubrrh; |
||||
volatile uint8_t * const _ubrrl; |
||||
volatile uint8_t * const _ucsra; |
||||
volatile uint8_t * const _ucsrb; |
||||
|
||||
// register magic numbers
|
||||
const uint8_t _u2x; |
||||
const uint8_t _portEnableBits; ///< rx, tx and rx interrupt enables
|
||||
const uint8_t _portTxBits; ///< tx data and completion interrupt enables
|
||||
|
||||
// ring buffers
|
||||
Buffer * const _rxBuffer; |
||||
Buffer * const _txBuffer; |
||||
bool _open; |
||||
|
||||
// whether writes to the port should block waiting
|
||||
// for enough space to appear
|
||||
bool _nonblocking_writes; |
||||
|
||||
/* Class Variables */ |
||||
|
||||
/// Allocates a buffer of the given size
|
||||
///
|
||||
/// @param buffer The buffer descriptor for which the buffer will
|
||||
/// will be allocated.
|
||||
/// @param size The desired buffer size.
|
||||
/// @returns True if the buffer was allocated successfully.
|
||||
///
|
||||
static bool _allocBuffer(Buffer *buffer, uint16_t size); |
||||
|
||||
/// Frees the allocated buffer in a descriptor
|
||||
///
|
||||
/// @param buffer The descriptor whose buffer should be freed.
|
||||
///
|
||||
static void _freeBuffer(Buffer *buffer); |
||||
|
||||
/// default receive buffer size
|
||||
static const uint16_t _default_rx_buffer_size = 4; |
||||
|
||||
/// default transmit buffer size
|
||||
static const uint16_t _default_tx_buffer_size = 16; |
||||
|
||||
/// maxium tx/rx buffer size
|
||||
static const uint16_t _max_buffer_size = 256; |
||||
}; |
||||
|
||||
extern AP_HAL_AVR::AVRUARTDriver::Buffer __AVRUARTDriver__rxBuffer[]; |
||||
extern AP_HAL_AVR::AVRUARTDriver::Buffer __AVRUARTDriver__txBuffer[]; |
||||
|
||||
/// Generic Rx/Tx vectors for a serial port - needs to know magic numbers
|
||||
///
|
||||
#define AVRUARTDriverHandler(_PORT, _RXVECTOR, _TXVECTOR, _UDR, _UCSRB, _TXBITS) \ |
||||
ISR(_RXVECTOR, ISR_BLOCK) \
|
||||
{ \
|
||||
uint8_t c; \
|
||||
uint8_t i; \
|
||||
\
|
||||
/* read the byte as quickly as possible */ \
|
||||
c = _UDR; \
|
||||
/* work out where the head will go next */ \
|
||||
i = (__AVRUARTDriver__rxBuffer[_PORT].head + 1) & __AVRUARTDriver__rxBuffer[_PORT].mask; \
|
||||
/* decide whether we have space for another byte */ \
|
||||
if (i != __AVRUARTDriver__rxBuffer[_PORT].tail) { \
|
||||
/* we do, move the head */ \
|
||||
__AVRUARTDriver__rxBuffer[_PORT].bytes[__AVRUARTDriver__rxBuffer[_PORT].head] = c; \
|
||||
__AVRUARTDriver__rxBuffer[_PORT].head = i; \
|
||||
} \
|
||||
} \
|
||||
ISR(_TXVECTOR, ISR_BLOCK) \
|
||||
{ \
|
||||
/* if there is another character to send */ \
|
||||
if (__AVRUARTDriver__txBuffer[_PORT].tail != __AVRUARTDriver__txBuffer[_PORT].head) { \
|
||||
_UDR = __AVRUARTDriver__txBuffer[_PORT].bytes[__AVRUARTDriver__txBuffer[_PORT].tail]; \
|
||||
/* increment the tail */ \
|
||||
__AVRUARTDriver__txBuffer[_PORT].tail = \
|
||||
(__AVRUARTDriver__txBuffer[_PORT].tail + 1) & __AVRUARTDriver__txBuffer[_PORT].mask; \
|
||||
} else { \
|
||||
/* there are no more bytes to send, disable the interrupt */ \
|
||||
if (__AVRUARTDriver__txBuffer[_PORT].head == __AVRUARTDriver__txBuffer[_PORT].tail) \
|
||||
_UCSRB &= ~_TXBITS; \
|
||||
} \
|
||||
} \
|
||||
struct hack |
||||
|
||||
//
|
||||
// Portability; convert various older sets of defines for U(S)ART0 up
|
||||
// to match the definitions for the 1280 and later devices.
|
||||
//
|
||||
#if !defined(USART0_RX_vect) |
||||
# if defined(USART_RX_vect) |
||||
# define USART0_RX_vect USART_RX_vect |
||||
# define USART0_UDRE_vect USART_UDRE_vect |
||||
# elif defined(UART0_RX_vect) |
||||
# define USART0_RX_vect UART0_RX_vect |
||||
# define USART0_UDRE_vect UART0_UDRE_vect |
||||
# endif |
||||
#endif |
||||
|
||||
#if !defined(USART1_RX_vect) |
||||
# if defined(UART1_RX_vect) |
||||
# define USART1_RX_vect UART1_RX_vect |
||||
# define USART1_UDRE_vect UART1_UDRE_vect |
||||
# endif |
||||
#endif |
||||
|
||||
#if !defined(UDR0) |
||||
# if defined(UDR) |
||||
# define UDR0 UDR |
||||
# define UBRR0H UBRRH |
||||
# define UBRR0L UBRRL |
||||
# define UCSR0A UCSRA |
||||
# define UCSR0B UCSRB |
||||
# define U2X0 U2X |
||||
# define RXEN0 RXEN |
||||
# define TXEN0 TXEN |
||||
# define RXCIE0 RXCIE |
||||
# define UDRIE0 UDRIE |
||||
# endif |
||||
#endif |
||||
|
||||
///
|
||||
/// Macro defining a AVRUARTDriver port instance.
|
||||
///
|
||||
#define AVRUARTDriverInstance(_name, _num) \ |
||||
AVRUARTDriver _name(_num, \
|
||||
&UBRR##_num##H, \
|
||||
&UBRR##_num##L, \
|
||||
&UCSR##_num##A, \
|
||||
&UCSR##_num##B, \
|
||||
U2X##_num, \
|
||||
(_BV(RXEN##_num) | _BV(TXEN##_num) | _BV(RXCIE##_num)), \
|
||||
(_BV(UDRIE##_num))); |
||||
|
||||
#define AVRUARTDriverISRs(_num) \ |
||||
AVRUARTDriverHandler(_num, \
|
||||
USART##_num##_RX_vect, \
|
||||
USART##_num##_UDRE_vect, \
|
||||
UDR##_num, \
|
||||
UCSR##_num##B, \
|
||||
_BV(UDRIE##_num)) |
||||
|
||||
#endif |
||||
#endif // __AP_HAL_AVR_UART_DRIVER_H__
|
||||
|
@ -1,15 +0,0 @@
@@ -1,15 +0,0 @@
|
||||
|
||||
#ifndef __AP_HAL_AVR_UTIL_H__ |
||||
#define __AP_HAL_AVR_UTIL_H__ |
||||
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#include "AP_HAL_AVR_Namespace.h" |
||||
#include "memcheck.h" |
||||
|
||||
class AP_HAL_AVR::AVRUtil : public AP_HAL::Util { |
||||
public: |
||||
bool run_debug_shell(AP_HAL::BetterStream *stream) { return false; } |
||||
uint16_t available_memory(void) { return memcheck_available_memory(); } |
||||
}; |
||||
|
||||
#endif // __AP_HAL_AVR_UTIL_H__
|
@ -1,92 +0,0 @@
@@ -1,92 +0,0 @@
|
||||
|
||||
#include <AP_Common/AP_Common.h> |
||||
#include <AP_Progmem/AP_Progmem.h> |
||||
#include <AP_HAL/AP_HAL.h> |
||||
#include <AP_HAL_AVR/AP_HAL_AVR.h> |
||||
|
||||
#include <AP_Common/AP_Common.h> |
||||
#include <AP_Progmem/AP_Progmem.h> |
||||
#include <AP_Menu/AP_Menu.h> |
||||
#include <AP_Param/AP_Param.h> |
||||
#include <AP_GPS/AP_GPS.h> // ArduPilot GPS library |
||||
#include <AP_ADC/AP_ADC.h> // ArduPilot Mega Analog to Digital Converter Library |
||||
#include <AP_Baro/AP_Baro.h> |
||||
#include <AP_Declination/AP_Declination.h> |
||||
#include <AP_Compass/AP_Compass.h> // ArduPilot Mega Magnetometer Library |
||||
#include <AP_Math/AP_Math.h> // ArduPilot Mega Vector/Matrix math Library |
||||
#include <AP_Curve/AP_Curve.h> // Curve used to linearlise throttle pwm to thrust |
||||
#include <AP_InertialSensor/AP_InertialSensor.h> // ArduPilot Mega Inertial Sensor (accel & gyro) Library |
||||
// (only included for makefile libpath to work)
|
||||
#include <AP_AHRS/AP_AHRS.h> |
||||
#include <AC_PID/AC_PID.h> // PID library |
||||
#include <AC_PID/AC_P.h> // P library |
||||
#include <RC_Channel/RC_Channel.h> // RC Channel Library |
||||
#include <AP_Motors/AP_Motors.h> // AP Motors library |
||||
#include <AP_ADC_AnalogSource/AP_ADC_AnalogSource.h> |
||||
#include <AP_RangeFinder/AP_RangeFinder.h> // Range finder library |
||||
#include <AP_OpticalFlow/AP_OpticalFlow.h> // Optical Flow library |
||||
#include <Filter/Filter.h> // Filter library |
||||
#include <AP_Buffer/AP_Buffer.h> // APM FIFO Buffer |
||||
#include <AP_Relay/AP_Relay.h> // APM relay |
||||
#include <AP_Camera/AP_Camera.h> // Photo or video camera |
||||
#include <AP_Mount/AP_Mount.h> // Camera/Antenna mount |
||||
#include <AP_Airspeed/AP_Airspeed.h> // needed for AHRS build |
||||
#include <AP_Vehicle/AP_Vehicle.h> // needed for AHRS build |
||||
#include <AP_Notify/AP_Notify.h> |
||||
#include <DataFlash/DataFlash.h> |
||||
#include <AP_InertialNav/AP_InertialNav.h> // ArduPilot Mega inertial navigation library |
||||
#include <GCS_MAVLink/GCS_MAVLink.h> |
||||
#include <AP_Mission/AP_Mission.h> |
||||
#include <StorageManager/StorageManager.h> |
||||
#include <AP_Terrain/AP_Terrain.h> |
||||
#include <AP_HAL_AVR/memcheck.h> |
||||
#include <AP_NavEKF/AP_NavEKF.h> |
||||
#include <AP_NavEKF/AP_Nav_Common.h> |
||||
#include <AP_BattMonitor/AP_BattMonitor.h> |
||||
|
||||
#if CONFIG_HAL_BOARD == HAL_BOARD_APM2 |
||||
const AP_HAL::HAL& hal = AP_HAL_AVR_APM2; |
||||
#elif CONFIG_HAL_BOARD == HAL_BOARD_APM1 |
||||
const AP_HAL::HAL& hal = AP_HAL_AVR_APM1; |
||||
#endif |
||||
|
||||
|
||||
void stream_loopback(AP_HAL::Stream* s, uint32_t time) { |
||||
uint32_t end = hal.scheduler->millis() + time; |
||||
for(;;) { |
||||
if (hal.scheduler->millis() >= end && time != 0) { |
||||
return; |
||||
} |
||||
if (s->available() > 0) { |
||||
int c; |
||||
c = s->read(); |
||||
if (-1 != c) { |
||||
s->write((uint8_t)c); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
void setup(void) |
||||
{ |
||||
//
|
||||
// Test printing things
|
||||
//
|
||||
hal.console->print("test"); |
||||
hal.console->println(" begin"); |
||||
hal.console->println(1000); |
||||
hal.console->println(1000, 8); |
||||
hal.console->println(1000, 10); |
||||
hal.console->println(1000, 16); |
||||
hal.console->println_P(PSTR("progmem")); |
||||
hal.console->printf("printf %d %u %#x %p %f %S\n", -1000, 1000, 1000, 1000, 1.2345, PSTR("progmem")); |
||||
hal.console->printf_P(PSTR("printf_P %d %u %#x %p %f %S\n"), -1000, 1000, 1000, 1000, 1.2345, PSTR("progmem")); |
||||
hal.console->println("done."); |
||||
for(;;); |
||||
|
||||
} |
||||
|
||||
|
||||
void loop(void){} |
||||
|
||||
AP_HAL_MAIN(); |
@ -1,2 +0,0 @@
@@ -1,2 +0,0 @@
|
||||
BOARD = mega
|
||||
include ../../../../mk/apm.mk |
@ -1,36 +0,0 @@
@@ -1,36 +0,0 @@
|
||||
LIBRARIES += AC_PID |
||||
LIBRARIES += AP_ADC |
||||
LIBRARIES += AP_ADC_AnalogSource |
||||
LIBRARIES += AP_AHRS |
||||
LIBRARIES += AP_Airspeed |
||||
LIBRARIES += AP_Baro |
||||
LIBRARIES += AP_BattMonitor |
||||
LIBRARIES += AP_Buffer |
||||
LIBRARIES += AP_Camera |
||||
LIBRARIES += AP_Common |
||||
LIBRARIES += AP_Compass |
||||
LIBRARIES += AP_Curve |
||||
LIBRARIES += AP_Declination |
||||
LIBRARIES += AP_GPS |
||||
LIBRARIES += AP_InertialNav |
||||
LIBRARIES += AP_InertialSensor |
||||
LIBRARIES += AP_Math |
||||
LIBRARIES += AP_Menu |
||||
LIBRARIES += AP_Mission |
||||
LIBRARIES += AP_Motors |
||||
LIBRARIES += AP_Mount |
||||
LIBRARIES += AP_NavEKF |
||||
LIBRARIES += AP_Notify |
||||
LIBRARIES += AP_OpticalFlow |
||||
LIBRARIES += AP_Param |
||||
LIBRARIES += AP_Progmem |
||||
LIBRARIES += AP_RangeFinder |
||||
LIBRARIES += AP_Relay |
||||
LIBRARIES += AP_Terrain |
||||
LIBRARIES += AP_Vehicle |
||||
LIBRARIES += DataFlash |
||||
LIBRARIES += Filter |
||||
LIBRARIES += GCS_MAVLink |
||||
LIBRARIES += memcheck |
||||
LIBRARIES += RC_Channel |
||||
LIBRARIES += StorageManager |
@ -1,70 +0,0 @@
@@ -1,70 +0,0 @@
|
||||
|
||||
|
||||
// Libraries
|
||||
#include <AP_Common/AP_Common.h> |
||||
#include <AP_Progmem/AP_Progmem.h> |
||||
#include <AP_Menu/AP_Menu.h> |
||||
#include <AP_Param/AP_Param.h> |
||||
#include <AP_GPS/AP_GPS.h> // ArduPilot GPS library |
||||
#include <AP_Baro/AP_Baro.h> // ArduPilot barometer library |
||||
#include <AP_Compass/AP_Compass.h> // ArduPilot Mega Magnetometer Library |
||||
#include <AP_Math/AP_Math.h> // ArduPilot Mega Vector/Matrix math Library |
||||
#include <AP_ADC/AP_ADC.h> // ArduPilot Mega Analog to Digital Converter Library |
||||
#include <AP_InertialSensor/AP_InertialSensor.h> // Inertial Sensor Library |
||||
#include <AP_AHRS/AP_AHRS.h> // ArduPilot Mega DCM Library |
||||
#include <PID/PID.h> // PID library |
||||
#include <RC_Channel/RC_Channel.h> // RC Channel Library |
||||
#include <AP_ADC_AnalogSource/AP_ADC_AnalogSource.h> |
||||
#include <AP_RangeFinder/AP_RangeFinder.h> // Range finder library |
||||
#include <Filter/Filter.h> // Filter library |
||||
#include <AP_Buffer/AP_Buffer.h> // APM FIFO Buffer |
||||
#include <AP_Relay/AP_Relay.h> // APM relay |
||||
#include <AP_Camera/AP_Camera.h> // Photo or video camera |
||||
#include <AP_Airspeed/AP_Airspeed.h> |
||||
#include <AP_Notify/AP_Notify.h> |
||||
#include <AP_HAL_AVR/memcheck.h> |
||||
|
||||
#include <DataFlash/DataFlash.h> |
||||
#include <APM_Control/APM_Control.h> |
||||
#include <AP_Vehicle/AP_Vehicle.h> |
||||
#include <GCS_MAVLink/GCS_MAVLink.h> // MAVLink GCS definitions |
||||
#include <AP_Mission/AP_Mission.h> |
||||
#include <StorageManager/StorageManager.h> |
||||
#include <AP_Terrain/AP_Terrain.h> |
||||
#include <AP_Mount/AP_Mount.h> // Camera/Antenna mount |
||||
#include <AP_Declination/AP_Declination.h> // ArduPilot Mega Declination Helper Library |
||||
#include <AP_BattMonitor/AP_BattMonitor.h> |
||||
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#include <AP_HAL_AVR/AP_HAL_AVR.h> |
||||
|
||||
#if CONFIG_HAL_BOARD == HAL_BOARD_APM2 |
||||
const AP_HAL::HAL& hal = AP_HAL_AVR_APM2; |
||||
#elif CONFIG_HAL_BOARD == HAL_BOARD_APM1 |
||||
const AP_HAL::HAL& hal = AP_HAL_AVR_APM1; |
||||
#endif |
||||
|
||||
|
||||
void setup(void) |
||||
{ |
||||
//
|
||||
// Test printing things
|
||||
//
|
||||
hal.console->print("test"); |
||||
hal.console->println(" begin"); |
||||
hal.console->println(1000); |
||||
hal.console->println(1000, 8); |
||||
hal.console->println(1000, 10); |
||||
hal.console->println(1000, 16); |
||||
hal.console->println_P(PSTR("progmem")); |
||||
hal.console->printf("printf %d %u %#x %p %f %S\n", -1000, 1000, 1000, 1000, 1.2345, PSTR("progmem")); |
||||
hal.console->printf_P(PSTR("printf_P %d %u %#x %p %f %S\n"), -1000, 1000, 1000, 1000, 1.2345, PSTR("progmem")); |
||||
|
||||
for(;;); |
||||
|
||||
} |
||||
|
||||
|
||||
void loop(void){} |
||||
|
||||
AP_HAL_MAIN(); |
@ -1,2 +0,0 @@
@@ -1,2 +0,0 @@
|
||||
BOARD = mega
|
||||
include ../../../../mk/apm.mk |
@ -1,32 +0,0 @@
@@ -1,32 +0,0 @@
|
||||
LIBRARIES += AP_ADC |
||||
LIBRARIES += AP_ADC_AnalogSource |
||||
LIBRARIES += AP_AHRS |
||||
LIBRARIES += AP_Airspeed |
||||
LIBRARIES += AP_Baro |
||||
LIBRARIES += AP_BattMonitor |
||||
LIBRARIES += AP_Buffer |
||||
LIBRARIES += AP_Camera |
||||
LIBRARIES += AP_Common |
||||
LIBRARIES += AP_Compass |
||||
LIBRARIES += AP_Declination |
||||
LIBRARIES += AP_GPS |
||||
LIBRARIES += AP_InertialSensor |
||||
LIBRARIES += AP_Math |
||||
LIBRARIES += APM_Control |
||||
LIBRARIES += AP_Menu |
||||
LIBRARIES += AP_Mission |
||||
LIBRARIES += AP_Mount |
||||
LIBRARIES += AP_Notify |
||||
LIBRARIES += AP_Param |
||||
LIBRARIES += AP_Progmem |
||||
LIBRARIES += AP_RangeFinder |
||||
LIBRARIES += AP_Relay |
||||
LIBRARIES += AP_Terrain |
||||
LIBRARIES += AP_Vehicle |
||||
LIBRARIES += DataFlash |
||||
LIBRARIES += Filter |
||||
LIBRARIES += GCS_MAVLink |
||||
LIBRARIES += memcheck |
||||
LIBRARIES += PID |
||||
LIBRARIES += RC_Channel |
||||
LIBRARIES += StorageManager |
@ -1,54 +0,0 @@
@@ -1,54 +0,0 @@
|
||||
|
||||
#include <AP_Common/AP_Common.h> |
||||
#include <AP_Math/AP_Math.h> |
||||
#include <AP_Param/AP_Param.h> |
||||
#include <StorageManager/StorageManager.h> |
||||
#include <AP_Progmem/AP_Progmem.h> |
||||
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#include <AP_HAL_AVR/AP_HAL_AVR.h> |
||||
|
||||
#if CONFIG_HAL_BOARD == HAL_BOARD_APM1 |
||||
const AP_HAL::HAL& hal = AP_HAL_AVR_APM1; |
||||
#elif CONFIG_HAL_BOARD == HAL_BOARD_APM2 |
||||
const AP_HAL::HAL& hal = AP_HAL_AVR_APM2; |
||||
#endif |
||||
|
||||
AP_HAL::DigitalSource *a_led; |
||||
AP_HAL::DigitalSource *b_led; |
||||
AP_HAL::DigitalSource *c_led; |
||||
|
||||
void loop (void) { |
||||
hal.scheduler->delay(1000); |
||||
hal.gpio->write(13, 1); |
||||
|
||||
a_led->write(1); |
||||
b_led->write(0); |
||||
c_led->write(1); |
||||
|
||||
hal.scheduler->delay(1000); |
||||
hal.gpio->write(13, 0); |
||||
|
||||
a_led->write(0); |
||||
b_led->write(1); |
||||
c_led->write(0); |
||||
} |
||||
|
||||
void setup (void) { |
||||
hal.gpio->pinMode(13, HAL_GPIO_OUTPUT); |
||||
hal.gpio->write(13, 0); |
||||
|
||||
a_led = hal.gpio->channel(27); |
||||
b_led = hal.gpio->channel(26); |
||||
c_led = hal.gpio->channel(25); |
||||
|
||||
a_led->mode(HAL_GPIO_OUTPUT); |
||||
b_led->mode(HAL_GPIO_OUTPUT); |
||||
c_led->mode(HAL_GPIO_OUTPUT); |
||||
|
||||
a_led->write(0); |
||||
b_led->write(0); |
||||
c_led->write(0); |
||||
} |
||||
|
||||
AP_HAL_MAIN(); |
@ -1 +0,0 @@
@@ -1 +0,0 @@
|
||||
include ../../../../mk/apm.mk |
@ -1,5 +0,0 @@
@@ -1,5 +0,0 @@
|
||||
LIBRARIES += AP_Common |
||||
LIBRARIES += AP_Math |
||||
LIBRARIES += AP_Param |
||||
LIBRARIES += AP_Progmem |
||||
LIBRARIES += StorageManager |
@ -1,46 +0,0 @@
@@ -1,46 +0,0 @@
|
||||
// -*- Mode: C++; c-basic-offset: 8; indent-tabs-mode: nil -*-
|
||||
|
||||
//
|
||||
// Example code for the AP_HAL AVRUARTDriver, based on FastSerial
|
||||
//
|
||||
// This code is placed into the public domain.
|
||||
//
|
||||
|
||||
#include <AP_Common/AP_Common.h> |
||||
#include <AP_Math/AP_Math.h> |
||||
#include <AP_Param/AP_Param.h> |
||||
#include <StorageManager/StorageManager.h> |
||||
#include <AP_Progmem/AP_Progmem.h> |
||||
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#include <AP_HAL_AVR/AP_HAL_AVR.h> |
||||
|
||||
#if CONFIG_HAL_BOARD == HAL_BOARD_APM2 |
||||
const AP_HAL::HAL& hal = AP_HAL_AVR_APM2; |
||||
#elif CONFIG_HAL_BOARD == HAL_BOARD_APM1 |
||||
const AP_HAL::HAL& hal = AP_HAL_AVR_APM1; |
||||
#endif |
||||
|
||||
void setup(void) |
||||
{ |
||||
//
|
||||
// Test printing things
|
||||
//
|
||||
hal.console->print("test"); |
||||
hal.console->println(" begin"); |
||||
hal.console->println(1000); |
||||
hal.console->println(1000, 8); |
||||
hal.console->println(1000, 10); |
||||
hal.console->println(1000, 16); |
||||
hal.console->println_P(PSTR("progmem")); |
||||
hal.console->printf("printf %d %u %#x %p %f %S\n", -1000, 1000, 1000, 1000, 1.2345, PSTR("progmem")); |
||||
hal.console->printf_P(PSTR("printf_P %d %u %#x %p %f %S\n"), -1000, 1000, 1000, 1000, 1.2345, PSTR("progmem")); |
||||
|
||||
for(;;); |
||||
|
||||
} |
||||
|
||||
|
||||
void loop(void){} |
||||
|
||||
AP_HAL_MAIN(); |
@ -1,2 +0,0 @@
@@ -1,2 +0,0 @@
|
||||
BOARD = mega
|
||||
include ../../../../mk/apm.mk |
@ -1,5 +0,0 @@
@@ -1,5 +0,0 @@
|
||||
LIBRARIES += AP_Common |
||||
LIBRARIES += AP_Math |
||||
LIBRARIES += AP_Param |
||||
LIBRARIES += AP_Progmem |
||||
LIBRARIES += StorageManager |
@ -1,57 +0,0 @@
@@ -1,57 +0,0 @@
|
||||
/*******************************************
|
||||
* Sample sketch that configures an HMC5883L 3 axis |
||||
* magnetometer to continuous mode and reads back |
||||
* the three axis of data. |
||||
*******************************************/ |
||||
|
||||
#include <AP_Common/AP_Common.h> |
||||
#include <AP_Math/AP_Math.h> |
||||
#include <AP_Param/AP_Param.h> |
||||
#include <StorageManager/StorageManager.h> |
||||
#include <AP_Progmem/AP_Progmem.h> |
||||
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#include <AP_HAL_AVR/AP_HAL_AVR.h> |
||||
|
||||
#if CONFIG_HAL_BOARD == HAL_BOARD_APM2 |
||||
const AP_HAL::HAL& hal = AP_HAL_AVR_APM2; |
||||
#elif CONFIG_HAL_BOARD == HAL_BOARD_APM1 |
||||
const AP_HAL::HAL& hal = AP_HAL_AVR_APM1; |
||||
#endif |
||||
|
||||
#define HMC5883L 0x1E |
||||
|
||||
void setup() { |
||||
hal.console->printf_P(PSTR("Initializing HMC5883L at address %x\r\n"), |
||||
HMC5883L); |
||||
|
||||
uint8_t stat = hal.i2c->writeRegister(HMC5883L,0x02,0x00); |
||||
if (stat == 0) { |
||||
hal.console->printf_P(PSTR("successful init\r\n")); |
||||
} else { |
||||
hal.console->printf_P(PSTR("failed init: return status %d\r\n"), |
||||
(int)stat); |
||||
for(;;); |
||||
} |
||||
} |
||||
|
||||
void loop() { |
||||
uint8_t data[6]; |
||||
//read 6 bytes (x,y,z) from the device
|
||||
uint8_t stat = hal.i2c->readRegisters(HMC5883L,0x03,6, data); |
||||
|
||||
if (stat == 0){ |
||||
int x, y, z; |
||||
x = data[0] << 8; |
||||
x |= data[1]; |
||||
y = data[2] << 8; |
||||
y |= data[3]; |
||||
z = data[4] << 8; |
||||
z |= data[5]; |
||||
hal.console->printf_P(PSTR("x: %d y: %d z: %d \r\n"), x, y, z); |
||||
} else {
|
||||
hal.console->printf_P(PSTR("i2c error: status %d\r\n"), (int)stat); |
||||
} |
||||
} |
||||
|
||||
AP_HAL_MAIN(); |
@ -1 +0,0 @@
@@ -1 +0,0 @@
|
||||
include ../../../../mk/apm.mk |
@ -1,5 +0,0 @@
@@ -1,5 +0,0 @@
|
||||
LIBRARIES += AP_Common |
||||
LIBRARIES += AP_Math |
||||
LIBRARIES += AP_Param |
||||
LIBRARIES += AP_Progmem |
||||
LIBRARIES += StorageManager |
@ -1,84 +0,0 @@
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
LiquidCrystal Library - Hello World |
||||
|
||||
Demonstrates the use a 16x2 LCD display. The LiquidCrystal |
||||
library works with all LCD displays that are compatible with the
|
||||
Hitachi HD44780 driver. There are many of them out there, and you |
||||
can usually tell them by the 16-pin interface. |
||||
|
||||
This sketch prints "Hello World!" to the LCD |
||||
and shows the time. |
||||
|
||||
The circuit: |
||||
* LCD RS pin to digital pin 12 |
||||
* LCD Enable pin to digital pin 11 |
||||
* LCD D4 pin to digital pin 5 |
||||
* LCD D5 pin to digital pin 4 |
||||
* LCD D6 pin to digital pin 3 |
||||
* LCD D7 pin to digital pin 2 |
||||
* LCD R/W pin to ground |
||||
* 10K resistor: |
||||
* ends to +5V and ground |
||||
* wiper to LCD VO pin (pin 3) |
||||
|
||||
Library originally added 18 Apr 2008 |
||||
by David A. Mellis |
||||
library modified 5 Jul 2009 |
||||
by Limor Fried (http://www.ladyada.net)
|
||||
example added 9 Jul 2009 |
||||
by Tom Igoe |
||||
modified 22 Nov 2010 |
||||
by Tom Igoe |
||||
|
||||
This example code is in the public domain. |
||||
|
||||
http://www.arduino.cc/en/Tutorial/LiquidCrystal
|
||||
*/ |
||||
|
||||
// include the library code:
|
||||
|
||||
#include <AP_Common/AP_Common.h> |
||||
#include <AP_Math/AP_Math.h> |
||||
#include <AP_Param/AP_Param.h> |
||||
#include <AP_Progmem/AP_Progmem.h> |
||||
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#include <AP_HAL_AVR/AP_HAL_AVR.h> |
||||
|
||||
#include "LCrystal.h" |
||||
|
||||
#if CONFIG_HAL_BOARD == HAL_BOARD_APM2 |
||||
const AP_HAL::HAL& hal = AP_HAL_AVR_APM2; |
||||
#elif CONFIG_HAL_BOARD == HAL_BOARD_APM1 |
||||
const AP_HAL::HAL& hal = AP_HAL_AVR_APM1; |
||||
#endif |
||||
|
||||
// initialize the library with the numbers of the interface pins
|
||||
LiquidCrystal lcd(8, 9, 4, 5, 6, 7); |
||||
|
||||
void setup() { |
||||
/* pin 54 is A0 on the mega */ |
||||
hal.gpio->pinMode(54, HAL_GPIO_INPUT); |
||||
// set up the LCD's number of columns and rows:
|
||||
lcd.begin(16, 2); |
||||
// Print a message to the LCD.
|
||||
lcd.print("hello, world!"); |
||||
} |
||||
|
||||
void loop() { |
||||
// set the cursor to column 0, line 1
|
||||
// (note: line 1 is the second row, since counting begins with 0):
|
||||
lcd.setCursor(0, 1); |
||||
// print the number of seconds since reset:
|
||||
lcd.print(hal.scheduler->millis()/1000); |
||||
|
||||
|
||||
lcd.setCursor(8, 1); /* Halfway over second row */ |
||||
if (hal.gpio->read(54)) { |
||||
lcd.print("high"); |
||||
} else { |
||||
lcd.print("low "); |
||||
} |
||||
} |
||||
|
||||
AP_HAL_MAIN(); |
@ -1,313 +0,0 @@
@@ -1,313 +0,0 @@
|
||||
#include "LCrystal.h" |
||||
|
||||
#include <stdio.h> |
||||
#include <string.h> |
||||
#include <inttypes.h> |
||||
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
|
||||
extern const AP_HAL::HAL& hal; |
||||
|
||||
// When the display powers up, it is configured as follows:
|
||||
//
|
||||
// 1. Display clear
|
||||
// 2. Function set:
|
||||
// DL = 1; 8-bit interface data
|
||||
// N = 0; 1-line display
|
||||
// F = 0; 5x8 dot character font
|
||||
// 3. Display on/off control:
|
||||
// D = 0; Display off
|
||||
// C = 0; Cursor off
|
||||
// B = 0; Blinking off
|
||||
// 4. Entry mode set:
|
||||
// I/D = 1; Increment by 1
|
||||
// S = 0; No shift
|
||||
//
|
||||
// Note, however, that resetting the Arduino doesn't reset the LCD, so we
|
||||
// can't assume that its in that state when a sketch starts (and the
|
||||
// LiquidCrystal constructor is called).
|
||||
|
||||
LiquidCrystal::LiquidCrystal(uint8_t rs, uint8_t rw, uint8_t enable, |
||||
uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, |
||||
uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7) |
||||
{ |
||||
init(0, rs, rw, enable, d0, d1, d2, d3, d4, d5, d6, d7); |
||||
} |
||||
|
||||
LiquidCrystal::LiquidCrystal(uint8_t rs, uint8_t enable, |
||||
uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, |
||||
uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7) |
||||
{ |
||||
init(0, rs, 255, enable, d0, d1, d2, d3, d4, d5, d6, d7); |
||||
} |
||||
|
||||
LiquidCrystal::LiquidCrystal(uint8_t rs, uint8_t rw, uint8_t enable, |
||||
uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3) |
||||
{ |
||||
init(1, rs, rw, enable, d0, d1, d2, d3, 0, 0, 0, 0); |
||||
} |
||||
|
||||
LiquidCrystal::LiquidCrystal(uint8_t rs, uint8_t enable, |
||||
uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3) |
||||
{ |
||||
init(1, rs, 255, enable, d0, d1, d2, d3, 0, 0, 0, 0); |
||||
} |
||||
|
||||
void LiquidCrystal::init(uint8_t fourbitmode, uint8_t rs, uint8_t rw, uint8_t enable, |
||||
uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, |
||||
uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7) |
||||
{ |
||||
_rs_pin = rs; |
||||
_rw_pin = rw; |
||||
_enable_pin = enable; |
||||
|
||||
_data_pins[0] = d0; |
||||
_data_pins[1] = d1; |
||||
_data_pins[2] = d2; |
||||
_data_pins[3] = d3;
|
||||
_data_pins[4] = d4; |
||||
_data_pins[5] = d5; |
||||
_data_pins[6] = d6; |
||||
_data_pins[7] = d7;
|
||||
|
||||
hal.gpio->pinMode(_rs_pin, HAL_GPIO_OUTPUT); |
||||
// we can save 1 pin by not using RW. Indicate by passing 255 instead of pin#
|
||||
if (_rw_pin != 255) {
|
||||
hal.gpio->pinMode(_rw_pin, HAL_GPIO_OUTPUT); |
||||
} |
||||
hal.gpio->pinMode(_enable_pin, HAL_GPIO_OUTPUT); |
||||
|
||||
if (fourbitmode) |
||||
_displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS; |
||||
else
|
||||
_displayfunction = LCD_8BITMODE | LCD_1LINE | LCD_5x8DOTS; |
||||
|
||||
begin(16, 1);
|
||||
} |
||||
|
||||
void LiquidCrystal::begin(uint8_t cols, uint8_t lines, uint8_t dotsize) { |
||||
if (lines > 1) { |
||||
_displayfunction |= LCD_2LINE; |
||||
} |
||||
_numlines = lines; |
||||
_currline = 0; |
||||
|
||||
// for some 1 line displays you can select a 10 pixel high font
|
||||
if ((dotsize != 0) && (lines == 1)) { |
||||
_displayfunction |= LCD_5x10DOTS; |
||||
} |
||||
|
||||
// SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION!
|
||||
// according to datasheet, we need at least 40ms after power rises above 2.7V
|
||||
// before sending commands. Arduino can turn on way befer 4.5V so we'll wait 50
|
||||
hal.scheduler->delay_microseconds(50000);
|
||||
// Now we pull both RS and R/W low to begin commands
|
||||
hal.gpio->write(_rs_pin, 0); |
||||
hal.gpio->write(_enable_pin, 0); |
||||
if (_rw_pin != 255) {
|
||||
hal.gpio->write(_rw_pin, 0); |
||||
} |
||||
|
||||
//put the LCD into 4 bit or 8 bit mode
|
||||
if (! (_displayfunction & LCD_8BITMODE)) { |
||||
// this is according to the hitachi HD44780 datasheet
|
||||
// figure 24, pg 46
|
||||
|
||||
// we start in 8bit mode, try to set 4 bit mode
|
||||
write4bits(0x03); |
||||
hal.scheduler->delay_microseconds(4500); // wait min 4.1ms
|
||||
|
||||
// second try
|
||||
write4bits(0x03); |
||||
hal.scheduler->delay_microseconds(4500); // wait min 4.1ms
|
||||
|
||||
// third go!
|
||||
write4bits(0x03);
|
||||
hal.scheduler->delay_microseconds(150); |
||||
|
||||
// finally, set to 4-bit interface
|
||||
write4bits(0x02);
|
||||
} else { |
||||
// this is according to the hitachi HD44780 datasheet
|
||||
// page 45 figure 23
|
||||
|
||||
// Send function set command sequence
|
||||
command(LCD_FUNCTIONSET | _displayfunction); |
||||
hal.scheduler->delay_microseconds(4500); // wait more than 4.1ms
|
||||
|
||||
// second try
|
||||
command(LCD_FUNCTIONSET | _displayfunction); |
||||
hal.scheduler->delay_microseconds(150); |
||||
|
||||
// third go
|
||||
command(LCD_FUNCTIONSET | _displayfunction); |
||||
} |
||||
|
||||
// finally, set # lines, font size, etc.
|
||||
command(LCD_FUNCTIONSET | _displayfunction);
|
||||
|
||||
// turn the display on with no cursor or blinking default
|
||||
_displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF;
|
||||
display(); |
||||
|
||||
// clear it off
|
||||
clear(); |
||||
|
||||
// Initialize to default text direction (for romance languages)
|
||||
_displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT; |
||||
// set the entry mode
|
||||
command(LCD_ENTRYMODESET | _displaymode); |
||||
|
||||
} |
||||
|
||||
/********** high level commands, for the user! */ |
||||
void LiquidCrystal::clear() |
||||
{ |
||||
command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero
|
||||
hal.scheduler->delay_microseconds(2000); // this command takes a long time!
|
||||
} |
||||
|
||||
void LiquidCrystal::home() |
||||
{ |
||||
command(LCD_RETURNHOME); // set cursor position to zero
|
||||
hal.scheduler->delay_microseconds(2000); // this command takes a long time!
|
||||
} |
||||
|
||||
void LiquidCrystal::setCursor(uint8_t col, uint8_t row) |
||||
{ |
||||
int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 }; |
||||
if ( row >= _numlines ) { |
||||
row = _numlines-1; // we count rows starting w/0
|
||||
} |
||||
|
||||
command(LCD_SETDDRAMADDR | (col + row_offsets[row])); |
||||
} |
||||
|
||||
// Turn the display on/off (quickly)
|
||||
void LiquidCrystal::noDisplay() { |
||||
_displaycontrol &= ~LCD_DISPLAYON; |
||||
command(LCD_DISPLAYCONTROL | _displaycontrol); |
||||
} |
||||
void LiquidCrystal::display() { |
||||
_displaycontrol |= LCD_DISPLAYON; |
||||
command(LCD_DISPLAYCONTROL | _displaycontrol); |
||||
} |
||||
|
||||
// Turns the underline cursor on/off
|
||||
void LiquidCrystal::noCursor() { |
||||
_displaycontrol &= ~LCD_CURSORON; |
||||
command(LCD_DISPLAYCONTROL | _displaycontrol); |
||||
} |
||||
void LiquidCrystal::cursor() { |
||||
_displaycontrol |= LCD_CURSORON; |
||||
command(LCD_DISPLAYCONTROL | _displaycontrol); |
||||
} |
||||
|
||||
// Turn on and off the blinking cursor
|
||||
void LiquidCrystal::noBlink() { |
||||
_displaycontrol &= ~LCD_BLINKON; |
||||
command(LCD_DISPLAYCONTROL | _displaycontrol); |
||||
} |
||||
void LiquidCrystal::blink() { |
||||
_displaycontrol |= LCD_BLINKON; |
||||
command(LCD_DISPLAYCONTROL | _displaycontrol); |
||||
} |
||||
|
||||
// These commands scroll the display without changing the RAM
|
||||
void LiquidCrystal::scrollDisplayLeft(void) { |
||||
command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT); |
||||
} |
||||
void LiquidCrystal::scrollDisplayRight(void) { |
||||
command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT); |
||||
} |
||||
|
||||
// This is for text that flows Left to Right
|
||||
void LiquidCrystal::leftToRight(void) { |
||||
_displaymode |= LCD_ENTRYLEFT; |
||||
command(LCD_ENTRYMODESET | _displaymode); |
||||
} |
||||
|
||||
// This is for text that flows Right to Left
|
||||
void LiquidCrystal::rightToLeft(void) { |
||||
_displaymode &= ~LCD_ENTRYLEFT; |
||||
command(LCD_ENTRYMODESET | _displaymode); |
||||
} |
||||
|
||||
// This will 'right justify' text from the cursor
|
||||
void LiquidCrystal::autoscroll(void) { |
||||
_displaymode |= LCD_ENTRYSHIFTINCREMENT; |
||||
command(LCD_ENTRYMODESET | _displaymode); |
||||
} |
||||
|
||||
// This will 'left justify' text from the cursor
|
||||
void LiquidCrystal::noAutoscroll(void) { |
||||
_displaymode &= ~LCD_ENTRYSHIFTINCREMENT; |
||||
command(LCD_ENTRYMODESET | _displaymode); |
||||
} |
||||
|
||||
// Allows us to fill the first 8 CGRAM locations
|
||||
// with custom characters
|
||||
void LiquidCrystal::createChar(uint8_t location, uint8_t charmap[]) { |
||||
location &= 0x7; // we only have 8 locations 0-7
|
||||
command(LCD_SETCGRAMADDR | (location << 3)); |
||||
for (int i=0; i<8; i++) { |
||||
write(charmap[i]); |
||||
} |
||||
} |
||||
|
||||
/*********** mid level commands, for sending data/cmds */ |
||||
|
||||
inline void LiquidCrystal::command(uint8_t value) { |
||||
send(value, 0); |
||||
} |
||||
|
||||
inline size_t LiquidCrystal::write(uint8_t value) { |
||||
send(value, 1); |
||||
return 1; // assume sucess
|
||||
} |
||||
|
||||
/************ low level data pushing commands **********/ |
||||
|
||||
// write either command or data, with automatic 4/8-bit selection
|
||||
void LiquidCrystal::send(uint8_t value, uint8_t mode) { |
||||
hal.gpio->write(_rs_pin, mode); |
||||
|
||||
// if there is a RW pin indicated, set it low to Write
|
||||
if (_rw_pin != 255) {
|
||||
hal.gpio->write(_rw_pin, 0); |
||||
} |
||||
|
||||
if (_displayfunction & LCD_8BITMODE) { |
||||
write8bits(value);
|
||||
} else { |
||||
write4bits(value>>4); |
||||
write4bits(value); |
||||
} |
||||
} |
||||
|
||||
void LiquidCrystal::pulseEnable(void) { |
||||
hal.gpio->write(_enable_pin, 0); |
||||
hal.scheduler->delay_microseconds(1);
|
||||
hal.gpio->write(_enable_pin, 1); |
||||
hal.scheduler->delay_microseconds(1); // enable pulse must be >450ns
|
||||
hal.gpio->write(_enable_pin, 0); |
||||
hal.scheduler->delay_microseconds(100); // commands need > 37us to settle
|
||||
} |
||||
|
||||
void LiquidCrystal::write4bits(uint8_t value) { |
||||
for (int i = 0; i < 4; i++) { |
||||
hal.gpio->pinMode(_data_pins[i], HAL_GPIO_OUTPUT); |
||||
hal.gpio->write(_data_pins[i], (value >> i) & 0x01); |
||||
} |
||||
|
||||
pulseEnable(); |
||||
} |
||||
|
||||
void LiquidCrystal::write8bits(uint8_t value) { |
||||
for (int i = 0; i < 8; i++) { |
||||
hal.gpio->pinMode(_data_pins[i], HAL_GPIO_OUTPUT); |
||||
hal.gpio->write(_data_pins[i], (value >> i) & 0x01); |
||||
} |
||||
|
||||
pulseEnable(); |
||||
} |
@ -1,106 +0,0 @@
@@ -1,106 +0,0 @@
|
||||
#ifndef LiquidCrystal_h |
||||
#define LiquidCrystal_h |
||||
|
||||
#include <inttypes.h> |
||||
#include <AP_HAL/utility/Print.h> |
||||
|
||||
// commands
|
||||
#define LCD_CLEARDISPLAY 0x01 |
||||
#define LCD_RETURNHOME 0x02 |
||||
#define LCD_ENTRYMODESET 0x04 |
||||
#define LCD_DISPLAYCONTROL 0x08 |
||||
#define LCD_CURSORSHIFT 0x10 |
||||
#define LCD_FUNCTIONSET 0x20 |
||||
#define LCD_SETCGRAMADDR 0x40 |
||||
#define LCD_SETDDRAMADDR 0x80 |
||||
|
||||
// flags for display entry mode
|
||||
#define LCD_ENTRYRIGHT 0x00 |
||||
#define LCD_ENTRYLEFT 0x02 |
||||
#define LCD_ENTRYSHIFTINCREMENT 0x01 |
||||
#define LCD_ENTRYSHIFTDECREMENT 0x00 |
||||
|
||||
// flags for display on/off control
|
||||
#define LCD_DISPLAYON 0x04 |
||||
#define LCD_DISPLAYOFF 0x00 |
||||
#define LCD_CURSORON 0x02 |
||||
#define LCD_CURSOROFF 0x00 |
||||
#define LCD_BLINKON 0x01 |
||||
#define LCD_BLINKOFF 0x00 |
||||
|
||||
// flags for display/cursor shift
|
||||
#define LCD_DISPLAYMOVE 0x08 |
||||
#define LCD_CURSORMOVE 0x00 |
||||
#define LCD_MOVERIGHT 0x04 |
||||
#define LCD_MOVELEFT 0x00 |
||||
|
||||
// flags for function set
|
||||
#define LCD_8BITMODE 0x10 |
||||
#define LCD_4BITMODE 0x00 |
||||
#define LCD_2LINE 0x08 |
||||
#define LCD_1LINE 0x00 |
||||
#define LCD_5x10DOTS 0x04 |
||||
#define LCD_5x8DOTS 0x00 |
||||
|
||||
class LiquidCrystal : public AP_HAL::Print { |
||||
public: |
||||
LiquidCrystal(uint8_t rs, uint8_t enable, |
||||
uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, |
||||
uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7); |
||||
LiquidCrystal(uint8_t rs, uint8_t rw, uint8_t enable, |
||||
uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, |
||||
uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7); |
||||
LiquidCrystal(uint8_t rs, uint8_t rw, uint8_t enable, |
||||
uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3); |
||||
LiquidCrystal(uint8_t rs, uint8_t enable, |
||||
uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3); |
||||
|
||||
void init(uint8_t fourbitmode, uint8_t rs, uint8_t rw, uint8_t enable, |
||||
uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, |
||||
uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7); |
||||
|
||||
void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS); |
||||
|
||||
void clear(); |
||||
void home(); |
||||
|
||||
void noDisplay(); |
||||
void display(); |
||||
void noBlink(); |
||||
void blink(); |
||||
void noCursor(); |
||||
void cursor(); |
||||
void scrollDisplayLeft(); |
||||
void scrollDisplayRight(); |
||||
void leftToRight(); |
||||
void rightToLeft(); |
||||
void autoscroll(); |
||||
void noAutoscroll(); |
||||
|
||||
void createChar(uint8_t, uint8_t[]); |
||||
void setCursor(uint8_t, uint8_t);
|
||||
virtual size_t write(uint8_t); |
||||
void command(uint8_t); |
||||
|
||||
using Print::write; |
||||
private: |
||||
void send(uint8_t, uint8_t); |
||||
void write4bits(uint8_t); |
||||
void write8bits(uint8_t); |
||||
void pulseEnable(); |
||||
|
||||
uint8_t _rs_pin; // LOW: command. HIGH: character.
|
||||
uint8_t _rw_pin; // LOW: write to LCD. HIGH: read from LCD.
|
||||
uint8_t _enable_pin; // activated by a HIGH pulse.
|
||||
uint8_t _data_pins[8]; |
||||
|
||||
uint8_t _displayfunction; |
||||
uint8_t _displaycontrol; |
||||
uint8_t _displaymode; |
||||
|
||||
uint8_t _initialized; |
||||
|
||||
uint8_t _numlines,_currline; |
||||
}; |
||||
|
||||
#endif |
@ -1 +0,0 @@
@@ -1 +0,0 @@
|
||||
include ../../../../mk/apm.mk |
@ -1,7 +0,0 @@
@@ -1,7 +0,0 @@
|
||||
|
||||
This is a quick test app based on the Arduino LiquidCrystal library, |
||||
modified to use an AP_HAL instead of the Arduino core. |
||||
|
||||
I tested it with a Freetronics 16x2 LCD shield v2 on an Arduino Mega 2560. |
||||
|
||||
Pat Hickey, 23 Aug 2012 |
@ -1,4 +0,0 @@
@@ -1,4 +0,0 @@
|
||||
LIBRARIES += AP_Common |
||||
LIBRARIES += AP_Math |
||||
LIBRARIES += AP_Param |
||||
LIBRARIES += AP_Progmem |
@ -1 +0,0 @@
@@ -1 +0,0 @@
|
||||
include ../../../../mk/apm.mk |
@ -1,69 +0,0 @@
@@ -1,69 +0,0 @@
|
||||
|
||||
#include <AP_Common/AP_Common.h> |
||||
#include <AP_Math/AP_Math.h> |
||||
#include <AP_Param/AP_Param.h> |
||||
#include <StorageManager/StorageManager.h> |
||||
#include <AP_Progmem/AP_Progmem.h> |
||||
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#include <AP_HAL_AVR/AP_HAL_AVR.h> |
||||
|
||||
#if CONFIG_HAL_BOARD == HAL_BOARD_APM2 |
||||
const AP_HAL::HAL& hal = AP_HAL_AVR_APM2; |
||||
#elif CONFIG_HAL_BOARD == HAL_BOARD_APM1 |
||||
const AP_HAL::HAL& hal = AP_HAL_AVR_APM1; |
||||
#endif |
||||
|
||||
void multiread(AP_HAL::RCInput* in) { |
||||
/* Multi-channel read method: */ |
||||
uint16_t channels[8]; |
||||
uint8_t valid; |
||||
valid = in->read(channels, 8); |
||||
hal.console->printf_P( |
||||
PSTR("multi read %d: %d %d %d %d %d %d %d %d\r\n"), |
||||
(int) valid,
|
||||
channels[0], channels[1], channels[2], channels[3], |
||||
channels[4], channels[5], channels[6], channels[7]); |
||||
} |
||||
|
||||
void individualread(AP_HAL::RCInput* in) { |
||||
/* individual channel read method: */ |
||||
bool valid; |
||||
uint16_t channels[8]; |
||||
valid = in->new_input(); |
||||
for (int i = 0; i < 8; i++) { |
||||
channels[i] = in->read(i); |
||||
} |
||||
hal.console->printf_P( |
||||
PSTR("individual read %d: %d %d %d %d %d %d %d %d\r\n"), |
||||
(int) valid,
|
||||
channels[0], channels[1], channels[2], channels[3], |
||||
channels[4], channels[5], channels[6], channels[7]); |
||||
} |
||||
|
||||
void loop (void) { |
||||
static int ctr = 0; |
||||
|
||||
hal.gpio->write(27, 1); |
||||
|
||||
/* Cycle between using the individual read method
|
||||
* and the multi read method*/ |
||||
if (ctr < 500) { |
||||
multiread(hal.rcin); |
||||
} else { |
||||
individualread(hal.rcin); |
||||
if (ctr > 1000) ctr = 0; |
||||
} |
||||
ctr++; |
||||
|
||||
hal.gpio->write(27, 0); |
||||
hal.scheduler->delay(2); |
||||
} |
||||
|
||||
void setup (void) { |
||||
hal.console->printf_P(PSTR("reading rc in:")); |
||||
hal.gpio->pinMode(27, HAL_GPIO_OUTPUT); |
||||
hal.gpio->write(27, 0); |
||||
} |
||||
|
||||
AP_HAL_MAIN(); |
@ -1,5 +0,0 @@
@@ -1,5 +0,0 @@
|
||||
LIBRARIES += AP_Common |
||||
LIBRARIES += AP_Math |
||||
LIBRARIES += AP_Param |
||||
LIBRARIES += AP_Progmem |
||||
LIBRARIES += StorageManager |
@ -1 +0,0 @@
@@ -1 +0,0 @@
|
||||
include ../../../../mk/apm.mk |
@ -1,121 +0,0 @@
@@ -1,121 +0,0 @@
|
||||
#include <AP_Common/AP_Common.h> |
||||
#include <AP_Math/AP_Math.h> |
||||
#include <AP_Param/AP_Param.h> |
||||
#include <StorageManager/StorageManager.h> |
||||
#include <AP_Progmem/AP_Progmem.h> |
||||
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#include <AP_HAL_AVR/AP_HAL_AVR.h> |
||||
|
||||
#if CONFIG_HAL_BOARD == HAL_BOARD_APM2 |
||||
const AP_HAL::HAL& hal = AP_HAL_AVR_APM2; |
||||
#elif CONFIG_HAL_BOARD == HAL_BOARD_APM1 |
||||
const AP_HAL::HAL& hal = AP_HAL_AVR_APM1; |
||||
#endif |
||||
|
||||
uint16_t ppm_center[ 8 ]; |
||||
uint16_t ppm_min[ 8 ]; |
||||
uint16_t ppm_max[ 8 ]; |
||||
uint16_t ppm_delta[ 8 ]; |
||||
uint16_t ppm_mark[ 8 ]; |
||||
|
||||
|
||||
void setup (void) { |
||||
hal.console->printf_P(PSTR("RC input jitter test - Do not move sticks:\n")); |
||||
|
||||
hal.scheduler->delay(2000); |
||||
|
||||
for( uint8_t rep = 0; rep < 10; rep++ ) |
||||
{ |
||||
for( uint8_t i = 0; i < 8; i++ ) |
||||
{ |
||||
uint16_t ppm_tmp = hal.rcin->read( i );
|
||||
ppm_center[ i ] += ppm_tmp; |
||||
} |
||||
hal.scheduler->delay( 100 );
|
||||
} |
||||
|
||||
for( uint8_t i = 0; i < 8; i++ ) |
||||
{ |
||||
uint16_t ppm_tmp = ppm_center[ i ] / 10; |
||||
ppm_center[ i ] = ppm_tmp; |
||||
ppm_min[ i ] = ppm_tmp; |
||||
ppm_max[ i ] = ppm_tmp; |
||||
ppm_delta[ i ] = 0; |
||||
}
|
||||
|
||||
} |
||||
|
||||
void loop (void) { |
||||
|
||||
|
||||
static bool update = true; |
||||
static uint32_t time_trigger; |
||||
|
||||
for( uint8_t i = 0; i < 8; i++ ) |
||||
{ |
||||
uint16_t ppm_tmp = hal.rcin->read( i ); |
||||
|
||||
// min?
|
||||
if( ppm_tmp < ppm_min[ i ] ) |
||||
{ |
||||
uint16_t delta_tmp = ppm_center[ i ] - ppm_tmp; |
||||
if( delta_tmp > ppm_delta[ i ] ) ppm_delta[ i ] = delta_tmp; |
||||
|
||||
ppm_min[ i ] = ppm_tmp; |
||||
ppm_mark[ i ] = ppm_tmp; |
||||
|
||||
update = true; |
||||
} |
||||
|
||||
// max?
|
||||
if( ppm_tmp > ppm_max[ i ] ) |
||||
{ |
||||
uint16_t delta_tmp = ppm_tmp - ppm_center[ i ]; |
||||
if( delta_tmp > ppm_delta[ i ] ) ppm_delta[ i ] = delta_tmp; |
||||
|
||||
ppm_max[ i ] = ppm_tmp; |
||||
ppm_mark[ i ] = ppm_tmp; |
||||
|
||||
update = true; |
||||
} |
||||
|
||||
} |
||||
|
||||
if( update && hal.scheduler->millis() > time_trigger ) |
||||
{ |
||||
update = false; |
||||
time_trigger = hal.scheduler->millis() + 5000; |
||||
|
||||
uint32_t time = hal.scheduler->millis() / 1000; |
||||
|
||||
uint16_t hour = time / 3600; |
||||
time -= hour * 3600; |
||||
|
||||
uint16_t minutte = time / 60; |
||||
time -= minutte * 60; |
||||
|
||||
uint16_t second = time; |
||||
|
||||
//hal.console->printf_P( PSTR("%c%c%c\r\n"), 0x1B, 0x5B, 0x48 ); // Terminal home position
|
||||
hal.console->printf_P( PSTR("\n< %.2u:%.2u:%.2u >------------------------------------- \n"), hour, minutte, second ); |
||||
for( uint8_t i = 0; i < 8; i++ )
|
||||
{ |
||||
hal.console->printf_P( PSTR("ch%d: center:%d min:%d max:%d delta:%d"), |
||||
i + 1, ppm_center[ i ], ppm_min[ i ],ppm_max[ i ], ppm_delta[ i ] );
|
||||
|
||||
if( ppm_mark[ i ] > 0 ) |
||||
{ |
||||
hal.console->printf_P( PSTR(" [%d]"), ppm_mark[ i ] ); |
||||
ppm_mark[ i ] = 0; |
||||
} |
||||
|
||||
hal.console->printf_P( PSTR("\n") ); |
||||
} |
||||
} |
||||
|
||||
hal.scheduler->delay( 10 ); |
||||
} |
||||
|
||||
AP_HAL_MAIN(); |
||||
|
@ -1,5 +0,0 @@
@@ -1,5 +0,0 @@
|
||||
LIBRARIES += AP_Common |
||||
LIBRARIES += AP_Math |
||||
LIBRARIES += AP_Param |
||||
LIBRARIES += AP_Progmem |
||||
LIBRARIES += StorageManager |
@ -1 +0,0 @@
@@ -1 +0,0 @@
|
||||
include ../../../../mk/apm.mk |
@ -1,101 +0,0 @@
@@ -1,101 +0,0 @@
|
||||
|
||||
#include <AP_Common/AP_Common.h> |
||||
#include <AP_Math/AP_Math.h> |
||||
#include <AP_Param/AP_Param.h> |
||||
#include <StorageManager/StorageManager.h> |
||||
#include <AP_Progmem/AP_Progmem.h> |
||||
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#include <AP_HAL_AVR/AP_HAL_AVR.h> |
||||
|
||||
#if CONFIG_HAL_BOARD == HAL_BOARD_APM2 |
||||
const AP_HAL::HAL& hal = AP_HAL_AVR_APM2; |
||||
#elif CONFIG_HAL_BOARD == HAL_BOARD_APM1 |
||||
const AP_HAL::HAL& hal = AP_HAL_AVR_APM1; |
||||
#endif |
||||
|
||||
void multiread(AP_HAL::RCInput* in, uint16_t* channels) { |
||||
/* Multi-channel read method: */ |
||||
uint8_t valid; |
||||
valid = in->read(channels, 8); |
||||
hal.console->printf_P( |
||||
PSTR("multi read %d: %d %d %d %d %d %d %d %d\r\n"), |
||||
(int) valid,
|
||||
channels[0], channels[1], channels[2], channels[3], |
||||
channels[4], channels[5], channels[6], channels[7]); |
||||
} |
||||
|
||||
void individualread(AP_HAL::RCInput* in, uint16_t* channels) { |
||||
/* individual channel read method: */ |
||||
bool valid; |
||||
valid = in->new_input(); |
||||
for (int i = 0; i < 8; i++) { |
||||
channels[i] = in->read(i); |
||||
} |
||||
hal.console->printf_P( |
||||
PSTR("individual read %d: %d %d %d %d %d %d %d %d\r\n"), |
||||
(int) valid,
|
||||
channels[0], channels[1], channels[2], channels[3], |
||||
channels[4], channels[5], channels[6], channels[7]); |
||||
} |
||||
|
||||
|
||||
void multiwrite(AP_HAL::RCOutput* out, uint16_t* channels) { |
||||
out->write(0, channels, 8); |
||||
/* Upper channels duplicate lower channels*/ |
||||
out->write(8, channels, 8); |
||||
} |
||||
|
||||
void individualwrite(AP_HAL::RCOutput* out, uint16_t* channels) { |
||||
for (int ch = 0; ch < 8; ch++) { |
||||
out->write(ch, channels[ch]);
|
||||
/* Upper channels duplicate lower channels*/ |
||||
out->write(ch+8, channels[ch]); |
||||
} |
||||
} |
||||
|
||||
void loop (void) { |
||||
static int ctr = 0; |
||||
uint16_t channels[8]; |
||||
|
||||
hal.gpio->write(27, 1); |
||||
|
||||
/* Cycle between using the individual read method
|
||||
* and the multi read method*/ |
||||
if (ctr < 500) { |
||||
multiread(hal.rcin, channels); |
||||
} else { |
||||
individualread(hal.rcin, channels); |
||||
if (ctr > 1000) ctr = 0; |
||||
} |
||||
|
||||
/* Cycle between individual output and multichannel output */ |
||||
if (ctr % 500 < 250) { |
||||
multiwrite(hal.rcout, channels); |
||||
} else { |
||||
individualwrite(hal.rcout, channels); |
||||
} |
||||
|
||||
hal.gpio->write(27, 0); |
||||
hal.scheduler->delay(4); |
||||
ctr++; |
||||
} |
||||
|
||||
void setup (void) { |
||||
hal.gpio->pinMode(27, HAL_GPIO_OUTPUT); |
||||
hal.gpio->write(27, 0); |
||||
for (uint8_t i=0; i<16; i++) { |
||||
hal.rcout->enable_ch(i); |
||||
} |
||||
|
||||
/* Bottom 4 channels at 400hz (like on a quad) */ |
||||
hal.rcout->set_freq(0x0000000F, 400); |
||||
for(int i = 0; i < 12; i++) { |
||||
hal.console->printf_P(PSTR("rcout ch %d has frequency %d\r\n"), |
||||
i, hal.rcout->get_freq(i)); |
||||
} |
||||
/* Delay to let the user see the above printouts on the terminal */ |
||||
hal.scheduler->delay(1000); |
||||
} |
||||
|
||||
AP_HAL_MAIN(); |
@ -1,5 +0,0 @@
@@ -1,5 +0,0 @@
|
||||
LIBRARIES += AP_Common |
||||
LIBRARIES += AP_Math |
||||
LIBRARIES += AP_Param |
||||
LIBRARIES += AP_Progmem |
||||
LIBRARIES += StorageManager |
@ -1,81 +0,0 @@
@@ -1,81 +0,0 @@
|
||||
|
||||
#ifndef __MPU6000_H__ |
||||
#define __MPU6000_H__ |
||||
// MPU 6000 registers
|
||||
#define MPUREG_WHOAMI 0x75 //
|
||||
#define MPUREG_SMPLRT_DIV 0x19 //
|
||||
#define MPUREG_CONFIG 0x1A //
|
||||
#define MPUREG_GYRO_CONFIG 0x1B |
||||
#define MPUREG_ACCEL_CONFIG 0x1C |
||||
#define MPUREG_FIFO_EN 0x23 |
||||
#define MPUREG_INT_PIN_CFG 0x37 |
||||
#define MPUREG_INT_ENABLE 0x38 |
||||
#define MPUREG_INT_STATUS 0x3A |
||||
#define MPUREG_ACCEL_XOUT_H 0x3B //
|
||||
#define MPUREG_ACCEL_XOUT_L 0x3C //
|
||||
#define MPUREG_ACCEL_YOUT_H 0x3D //
|
||||
#define MPUREG_ACCEL_YOUT_L 0x3E //
|
||||
#define MPUREG_ACCEL_ZOUT_H 0x3F //
|
||||
#define MPUREG_ACCEL_ZOUT_L 0x40 //
|
||||
#define MPUREG_TEMP_OUT_H 0x41//
|
||||
#define MPUREG_TEMP_OUT_L 0x42//
|
||||
#define MPUREG_GYRO_XOUT_H 0x43 //
|
||||
#define MPUREG_GYRO_XOUT_L 0x44 //
|
||||
#define MPUREG_GYRO_YOUT_H 0x45 //
|
||||
#define MPUREG_GYRO_YOUT_L 0x46 //
|
||||
#define MPUREG_GYRO_ZOUT_H 0x47 //
|
||||
#define MPUREG_GYRO_ZOUT_L 0x48 //
|
||||
#define MPUREG_USER_CTRL 0x6A //
|
||||
#define MPUREG_PWR_MGMT_1 0x6B //
|
||||
#define MPUREG_PWR_MGMT_2 0x6C //
|
||||
#define MPUREG_FIFO_COUNTH 0x72 |
||||
#define MPUREG_FIFO_COUNTL 0x73 |
||||
#define MPUREG_FIFO_R_W 0x74 |
||||
#define MPUREG_PRODUCT_ID 0x0C // Product ID Register
|
||||
|
||||
|
||||
// Configuration bits MPU 3000 and MPU 6000 (not revised)?
|
||||
#define BIT_SLEEP 0x40 |
||||
#define BIT_H_RESET 0x80 |
||||
#define BITS_CLKSEL 0x07 |
||||
#define MPU_CLK_SEL_PLLGYROX 0x01 |
||||
#define MPU_CLK_SEL_PLLGYROZ 0x03 |
||||
#define MPU_EXT_SYNC_GYROX 0x02 |
||||
#define BITS_FS_250DPS 0x00 |
||||
#define BITS_FS_500DPS 0x08 |
||||
#define BITS_FS_1000DPS 0x10 |
||||
#define BITS_FS_2000DPS 0x18 |
||||
#define BITS_FS_MASK 0x18 |
||||
#define BITS_DLPF_CFG_256HZ_NOLPF2 0x00 |
||||
#define BITS_DLPF_CFG_188HZ 0x01 |
||||
#define BITS_DLPF_CFG_98HZ 0x02 |
||||
#define BITS_DLPF_CFG_42HZ 0x03 |
||||
#define BITS_DLPF_CFG_20HZ 0x04 |
||||
#define BITS_DLPF_CFG_10HZ 0x05 |
||||
#define BITS_DLPF_CFG_5HZ 0x06 |
||||
#define BITS_DLPF_CFG_2100HZ_NOLPF 0x07 |
||||
#define BITS_DLPF_CFG_MASK 0x07 |
||||
#define BIT_INT_ANYRD_2CLEAR 0x10 |
||||
#define BIT_RAW_RDY_EN 0x01 |
||||
#define BIT_I2C_IF_DIS 0x10 |
||||
#define BIT_INT_STATUS_DATA 0x01 |
||||
|
||||
|
||||
// Product ID Description for MPU6000
|
||||
// high 4 bits low 4 bits
|
||||
// Product Name Product Revision
|
||||
#define MPU6000ES_REV_C4 0x14 // 0001 0100
|
||||
#define MPU6000ES_REV_C5 0x15 // 0001 0101
|
||||
#define MPU6000ES_REV_D6 0x16 // 0001 0110
|
||||
#define MPU6000ES_REV_D7 0x17 // 0001 0111
|
||||
#define MPU6000ES_REV_D8 0x18 // 0001 1000
|
||||
#define MPU6000_REV_C4 0x54 // 0101 0100
|
||||
#define MPU6000_REV_C5 0x55 // 0101 0101
|
||||
#define MPU6000_REV_D6 0x56 // 0101 0110
|
||||
#define MPU6000_REV_D7 0x57 // 0101 0111
|
||||
#define MPU6000_REV_D8 0x58 // 0101 1000
|
||||
#define MPU6000_REV_D9 0x59 // 0101 1001
|
||||
|
||||
|
||||
|
||||
#endif // __MPU6000_H__
|
@ -1 +0,0 @@
@@ -1 +0,0 @@
|
||||
include ../../../../mk/apm.mk |
@ -1,131 +0,0 @@
@@ -1,131 +0,0 @@
|
||||
/*******************************************
|
||||
* Sample sketch that configures an MPU6000 |
||||
* and reads back the three axis of accel, |
||||
* temperature, three axis of gyro data |
||||
*******************************************/ |
||||
|
||||
#include <AP_Common/AP_Common.h> |
||||
#include <AP_Math/AP_Math.h> |
||||
#include <AP_Param/AP_Param.h> |
||||
#include <StorageManager/StorageManager.h> |
||||
#include <AP_Progmem/AP_Progmem.h> |
||||
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#include <AP_HAL_AVR/AP_HAL_AVR.h> |
||||
|
||||
/* register #defines */ |
||||
#include "MPU6000.h" |
||||
|
||||
// debug only:
|
||||
#include <avr/io.h> |
||||
|
||||
#if CONFIG_HAL_BOARD == HAL_BOARD_APM2 |
||||
const AP_HAL::HAL& hal = AP_HAL_AVR_APM2; |
||||
#elif CONFIG_HAL_BOARD == HAL_BOARD_APM1 |
||||
const AP_HAL::HAL& hal = AP_HAL_AVR_APM1; |
||||
#endif |
||||
|
||||
AP_HAL::SPIDeviceDriver* spidev; |
||||
|
||||
static void register_write(uint8_t reg, uint8_t val) { |
||||
hal.console->printf_P(PSTR("write reg %d val %d\r\n"), |
||||
(int) reg, (int) val); |
||||
spidev->cs_assert(); |
||||
spidev->transfer(reg); |
||||
spidev->transfer(val); |
||||
spidev->cs_release(); |
||||
} |
||||
|
||||
static uint8_t register_read(uint8_t reg) { |
||||
/* set most significant bit to read register */ |
||||
uint8_t regaddr = reg | 0x80; |
||||
spidev->cs_assert(); |
||||
spidev->transfer(regaddr); |
||||
uint8_t val = spidev->transfer(0); |
||||
spidev->cs_release(); |
||||
return val; |
||||
} |
||||
|
||||
static uint16_t spi_read_16(void) { |
||||
uint8_t byte_h, byte_l; |
||||
byte_h = spidev->transfer(0); |
||||
byte_l = spidev->transfer(0); |
||||
return (((int16_t) byte_h)<< 8) | byte_l; |
||||
} |
||||
|
||||
|
||||
static void mpu6k_init(void) { |
||||
// chip reset
|
||||
register_write(MPUREG_PWR_MGMT_1, BIT_H_RESET); |
||||
hal.scheduler->delay(100); |
||||
// Wake up device and select GyroZ clock (better performance)
|
||||
register_write(MPUREG_PWR_MGMT_1, MPU_CLK_SEL_PLLGYROZ); |
||||
hal.scheduler->delay(1); |
||||
register_write(MPUREG_PWR_MGMT_2, 0); |
||||
hal.scheduler->delay(1); |
||||
// Disable I2C bus (recommended on datasheet)
|
||||
register_write(MPUREG_USER_CTRL, BIT_I2C_IF_DIS); |
||||
hal.scheduler->delay(1); |
||||
// SAMPLE RATE
|
||||
//// Sample rate = 200Hz Fsample= 1Khz/(4+1) = 200Hz
|
||||
register_write(MPUREG_SMPLRT_DIV,0x04); |
||||
hal.scheduler->delay(1); |
||||
// FS & DLPF FS=2000º/s, DLPF = 98Hz (low pass filter)
|
||||
register_write(MPUREG_CONFIG, BITS_DLPF_CFG_98HZ); |
||||
hal.scheduler->delay(1); |
||||
register_write(MPUREG_GYRO_CONFIG,BITS_FS_2000DPS); // Gyro scale 2000º/s
|
||||
hal.scheduler->delay(1); |
||||
|
||||
// read the product ID rev c has 1/2 the sensitivity of rev d
|
||||
uint8_t _product_id = register_read(MPUREG_PRODUCT_ID); |
||||
|
||||
//Serial.printf("Product_ID= 0x%x\n", (unsigned) _product_id);
|
||||
|
||||
if ((_product_id == MPU6000ES_REV_C4) || (_product_id == MPU6000ES_REV_C5) |
||||
||(_product_id == MPU6000_REV_C4) || (_product_id == MPU6000_REV_C5)){ |
||||
// Accel scale 8g (4096 LSB/g)
|
||||
// Rev C has different scaling than rev D
|
||||
register_write(MPUREG_ACCEL_CONFIG,1<<3); |
||||
} else { |
||||
// Accel scale 8g (4096 LSB/g)
|
||||
register_write(MPUREG_ACCEL_CONFIG,2<<3); |
||||
} |
||||
hal.scheduler->delay(1); |
||||
|
||||
// INT CFG => Interrupt on Data Ready
|
||||
//// INT: Raw data ready
|
||||
register_write(MPUREG_INT_ENABLE,BIT_RAW_RDY_EN); |
||||
hal.scheduler->delay(1); |
||||
// INT: Clear on any read
|
||||
register_write(MPUREG_INT_PIN_CFG,BIT_INT_ANYRD_2CLEAR);
|
||||
hal.scheduler->delay(1); |
||||
|
||||
} |
||||
|
||||
static void mpu6k_read(int16_t* data) { |
||||
|
||||
spidev->cs_assert(); |
||||
spidev->transfer( MPUREG_ACCEL_XOUT_H | 0x80 ); |
||||
for (int i = 0; i < 7; i++) { |
||||
data[i] = spi_read_16(); |
||||
} |
||||
spidev->cs_release(); |
||||
} |
||||
|
||||
static void setup() { |
||||
hal.console->printf_P(PSTR("Initializing MPU6000\r\n")); |
||||
spidev = hal.spi->device(AP_HAL::SPIDevice_MPU6000); |
||||
|
||||
mpu6k_init(); |
||||
} |
||||
|
||||
static void loop() { |
||||
int16_t sensors[7]; |
||||
mpu6k_read(sensors); |
||||
hal.console->printf_P(PSTR("mpu6k: %d %d %d %d %d %d %d\r\n"), |
||||
sensors[0], sensors[1], sensors[2], |
||||
sensors[3], sensors[4], sensors[5], sensors[6]); |
||||
hal.scheduler->delay(10); |
||||
} |
||||
|
||||
AP_HAL_MAIN(); |
@ -1,5 +0,0 @@
@@ -1,5 +0,0 @@
|
||||
LIBRARIES += AP_Common |
||||
LIBRARIES += AP_Math |
||||
LIBRARIES += AP_Param |
||||
LIBRARIES += AP_Progmem |
||||
LIBRARIES += StorageManager |
@ -1 +0,0 @@
@@ -1 +0,0 @@
|
||||
include ../../../../mk/apm.mk |
@ -1,113 +0,0 @@
@@ -1,113 +0,0 @@
|
||||
|
||||
#include <AP_Common/AP_Common.h> |
||||
#include <AP_Math/AP_Math.h> |
||||
#include <AP_Param/AP_Param.h> |
||||
#include <AP_Progmem/AP_Progmem.h> |
||||
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#include <AP_HAL_AVR/AP_HAL_AVR.h> |
||||
|
||||
#if CONFIG_HAL_BOARD == HAL_BOARD_APM2 |
||||
const AP_HAL::HAL& hal = AP_HAL_AVR_APM2; |
||||
#elif CONFIG_HAL_BOARD == HAL_BOARD_APM1 |
||||
const AP_HAL::HAL& hal = AP_HAL_AVR_APM1; |
||||
#endif |
||||
|
||||
/**
|
||||
* You'll want to use a logic analyzer to watch the effects of this test. |
||||
* On the APM2 its pretty easy to hook up an analyzer to pins A0 through A3. |
||||
*/ |
||||
#define DELAY_TOGGLE_PIN 54 /* A0 */ |
||||
#define FAILSAFE_TOGGLE_PIN 55 /* A1 */ |
||||
#define SCHEDULED_TOGGLE_PIN_1 56 /* A2 */ |
||||
#define SCHEDULED_TOGGLE_PIN_2 57 /* A3 */ |
||||
|
||||
|
||||
void delay_toggle() { |
||||
volatile int i; |
||||
hal.gpio->write(DELAY_TOGGLE_PIN, 1); |
||||
for (i = 0; i < 10; i++); |
||||
hal.gpio->write(DELAY_TOGGLE_PIN, 0); |
||||
} |
||||
|
||||
void failsafe_toggle(void *) { |
||||
volatile int i; |
||||
hal.gpio->write(FAILSAFE_TOGGLE_PIN, 1); |
||||
for (i = 0; i < 10; i++); |
||||
hal.gpio->write(FAILSAFE_TOGGLE_PIN, 0); |
||||
} |
||||
|
||||
|
||||
void schedule_toggle_1(void *) { |
||||
volatile int i; |
||||
hal.gpio->write(SCHEDULED_TOGGLE_PIN_1, 1); |
||||
for (i = 0; i < 10; i++); |
||||
hal.gpio->write(SCHEDULED_TOGGLE_PIN_1, 0); |
||||
} |
||||
|
||||
void schedule_toggle_2(void *) { |
||||
volatile int i; |
||||
hal.gpio->write(SCHEDULED_TOGGLE_PIN_2, 1); |
||||
for (i = 0; i < 10; i++); |
||||
hal.gpio->write(SCHEDULED_TOGGLE_PIN_2, 0); |
||||
} |
||||
|
||||
void schedule_toggle_hang(void *) { |
||||
hal.gpio->write(SCHEDULED_TOGGLE_PIN_2, 1);
|
||||
for(;;); |
||||
} |
||||
|
||||
void setup_pin(int pin_num) { |
||||
hal.console->printf_P(PSTR("Setup pin %d\r\n"), pin_num); |
||||
hal.gpio->pinMode(pin_num,HAL_GPIO_OUTPUT); |
||||
/* Blink so we can see setup on the logic analyzer.*/ |
||||
hal.gpio->write(pin_num,1); |
||||
hal.gpio->write(pin_num,0); |
||||
} |
||||
|
||||
void setup (void) { |
||||
hal.console->printf_P(PSTR("Starting AP_HAL_AVR::Scheduler test\r\n")); |
||||
|
||||
setup_pin(DELAY_TOGGLE_PIN); |
||||
setup_pin(FAILSAFE_TOGGLE_PIN); |
||||
setup_pin(SCHEDULED_TOGGLE_PIN_1); |
||||
setup_pin(SCHEDULED_TOGGLE_PIN_2); |
||||
|
||||
hal.console->printf_P(PSTR("Testing delay callback. " |
||||
"Pin %d should toggle at 1khz:\r\n"), |
||||
(int) DELAY_TOGGLE_PIN); |
||||
|
||||
hal.scheduler->register_delay_callback(delay_toggle,0); |
||||
|
||||
hal.scheduler->delay(100); |
||||
|
||||
hal.console->printf_P(PSTR("Testing failsafe callback. " |
||||
"Pin %d should toggle at 1khz:\r\n"), |
||||
(int) FAILSAFE_TOGGLE_PIN); |
||||
|
||||
hal.scheduler->register_timer_failsafe(failsafe_toggle, 1000); |
||||
|
||||
hal.scheduler->delay(100); |
||||
|
||||
hal.console->printf_P(PSTR("Testing running timer processes.\r\n")); |
||||
hal.console->printf_P(PSTR("Pin %d should toggle at 1khz.\r\n"), |
||||
(int) SCHEDULED_TOGGLE_PIN_1); |
||||
hal.console->printf_P(PSTR("Pin %d should toggle at 1khz.\r\n"), |
||||
(int) SCHEDULED_TOGGLE_PIN_2); |
||||
|
||||
hal.scheduler->register_timer_process(schedule_toggle_1, NULL); |
||||
hal.scheduler->register_timer_process(schedule_toggle_2, NULL); |
||||
|
||||
hal.scheduler->delay(100); |
||||
|
||||
hal.console->printf_P(PSTR("Test running a pathological timer process.\r\n" |
||||
"Failsafe should continue even as pathological process " |
||||
"dominates the processor.")); |
||||
hal.console->printf_P(PSTR("Pin %d should toggle then go high forever.\r\n"), |
||||
(int) SCHEDULED_TOGGLE_PIN_2); |
||||
hal.scheduler->register_timer_process(schedule_toggle_hang, NULL); |
||||
} |
||||
|
||||
void loop (void) { } |
||||
|
||||
AP_HAL_MAIN(); |
@ -1,4 +0,0 @@
@@ -1,4 +0,0 @@
|
||||
LIBRARIES += AP_Common |
||||
LIBRARIES += AP_Math |
||||
LIBRARIES += AP_Param |
||||
LIBRARIES += AP_Progmem |
@ -1 +0,0 @@
@@ -1 +0,0 @@
|
||||
include ../../../../mk/apm.mk |
@ -1,118 +0,0 @@
@@ -1,118 +0,0 @@
|
||||
#include <AP_Common/AP_Common.h> |
||||
#include <AP_Math/AP_Math.h> |
||||
#include <AP_Param/AP_Param.h> |
||||
#include <AP_Progmem/AP_Progmem.h> |
||||
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#include <AP_HAL_AVR/AP_HAL_AVR.h> |
||||
|
||||
const AP_HAL::HAL& hal = AP_HAL::get_HAL(); |
||||
|
||||
/**
|
||||
* You'll want to use a logic analyzer to watch the effects of this test. |
||||
* On the APM2 its pretty easy to hook up an analyzer to pins A0 through A3. |
||||
*/ |
||||
#define PIN_A0 54 /* A0 */ |
||||
#define PIN_A1 55 /* A1 */ |
||||
#define PIN_A2 56 /* A2 */ |
||||
#define PIN_A3 57 /* A3 */ |
||||
|
||||
/**
|
||||
* Create an AVRSemaphore for this test. |
||||
*/ |
||||
|
||||
AP_HAL::Semaphore *sem; |
||||
|
||||
void blink_a0() { |
||||
volatile int i; |
||||
hal.gpio->write(PIN_A0, 1); |
||||
for (i = 0; i < 10; i++); |
||||
hal.gpio->write(PIN_A0, 0); |
||||
} |
||||
|
||||
void blink_a1() { |
||||
volatile int i; |
||||
hal.gpio->write(PIN_A1, 1); |
||||
for (i = 0; i < 10; i++); |
||||
hal.gpio->write(PIN_A1, 0); |
||||
} |
||||
|
||||
|
||||
void blink_a2() { |
||||
volatile int i; |
||||
hal.gpio->write(PIN_A2, 1); |
||||
for (i = 0; i < 10; i++); |
||||
hal.gpio->write(PIN_A2, 0); |
||||
} |
||||
|
||||
void blink_a3() { |
||||
volatile int i; |
||||
hal.gpio->write(PIN_A3, 1); |
||||
for (i = 0; i < 10; i++); |
||||
hal.gpio->write(PIN_A3, 0); |
||||
} |
||||
|
||||
void setup_pin(int pin_num) { |
||||
hal.console->printf_P(PSTR("Setup pin %d\r\n"), pin_num); |
||||
hal.gpio->pinMode(pin_num,HAL_GPIO_OUTPUT); |
||||
/* Blink so we can see setup on the logic analyzer.*/ |
||||
hal.gpio->write(pin_num,1); |
||||
hal.gpio->write(pin_num,0); |
||||
} |
||||
|
||||
void setup (void) { |
||||
hal.console->printf_P(PSTR("Starting Semaphore test\r\n")); |
||||
|
||||
setup_pin(PIN_A0); |
||||
setup_pin(PIN_A1); |
||||
setup_pin(PIN_A2); |
||||
setup_pin(PIN_A3); |
||||
|
||||
hal.console->printf_P(PSTR("Using Dataflash's Semaphore\r\n")); |
||||
|
||||
AP_HAL::SPIDeviceDriver *dataflash = hal.spi->device( |
||||
AP_HAL::SPIDevice_Dataflash); |
||||
|
||||
if (dataflash == NULL) { |
||||
hal.scheduler->panic(PSTR("Error: No SPIDevice_Dataflash driver!")); |
||||
} |
||||
|
||||
sem = dataflash->get_semaphore(); |
||||
if (sem == NULL) { |
||||
hal.scheduler->panic(PSTR("Error: No SPIDeviceDriver semaphore!")); |
||||
} |
||||
|
||||
hal.scheduler->register_timer_process(async_blinker, NULL); |
||||
} |
||||
|
||||
|
||||
static uint32_t async_last_run; |
||||
|
||||
void async_blinker(void *)
|
||||
{ |
||||
uint32_t now = hal.scheduler->millis(); |
||||
if ((now - async_last_run) < 5) { |
||||
return; |
||||
} |
||||
async_last_run = now; |
||||
|
||||
if (sem->take_nonblocking()) { |
||||
blink_a0(); |
||||
sem->give(); |
||||
} else { |
||||
blink_a1(); |
||||
} |
||||
} |
||||
|
||||
void loop (void) { |
||||
|
||||
if (sem->take(1)) { |
||||
blink_a2(); |
||||
sem->give(); |
||||
} else { |
||||
/* This should never happen: */ |
||||
blink_a3();
|
||||
} |
||||
} |
||||
|
||||
AP_HAL_MAIN(); |
@ -1,4 +0,0 @@
@@ -1,4 +0,0 @@
|
||||
LIBRARIES += AP_Common |
||||
LIBRARIES += AP_Math |
||||
LIBRARIES += AP_Param |
||||
LIBRARIES += AP_Progmem |
@ -1 +0,0 @@
@@ -1 +0,0 @@
|
||||
include ../../../../mk/apm.mk |
@ -1,51 +0,0 @@
@@ -1,51 +0,0 @@
|
||||
|
||||
#include <AP_Common/AP_Common.h> |
||||
#include <AP_Math/AP_Math.h> |
||||
#include <AP_Param/AP_Param.h> |
||||
#include <StorageManager/StorageManager.h> |
||||
#include <AP_Progmem/AP_Progmem.h> |
||||
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#include <AP_HAL_AVR/AP_HAL_AVR.h> |
||||
|
||||
#if CONFIG_HAL_BOARD == HAL_BOARD_APM2 |
||||
const AP_HAL::HAL& hal = AP_HAL_AVR_APM2; |
||||
#elif CONFIG_HAL_BOARD == HAL_BOARD_APM1 |
||||
const AP_HAL::HAL& hal = AP_HAL_AVR_APM1; |
||||
#endif |
||||
|
||||
uint8_t fibs[12] = { 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144 }; |
||||
|
||||
void test_write() { |
||||
hal.console->printf_P(PSTR("writing... ")); |
||||
hal.storage->write_block(0, fibs, 12); |
||||
hal.console->printf_P(PSTR(" done.\r\n")); |
||||
} |
||||
|
||||
void test_readback() { |
||||
hal.console->printf_P(PSTR("reading back...\r\n")); |
||||
uint8_t readback[12]; |
||||
bool success = true; |
||||
hal.storage->read_block(readback, 0, 12); |
||||
for (int i = 0; i < 12; i++) { |
||||
if (readback[i] != fibs[i]) { |
||||
success = false; |
||||
hal.console->printf_P(PSTR("At index %d expected %d got %d\r\n"), |
||||
i, (int) fibs[i], (int) readback[i]);
|
||||
}
|
||||
} |
||||
if (success) { |
||||
hal.console->printf_P(PSTR("all bytes read successfully\r\n")); |
||||
} |
||||
hal.console->printf_P(PSTR("done reading back.\r\n")); |
||||
} |
||||
|
||||
void setup (void) { |
||||
hal.console->printf_P(PSTR("Starting AP_HAL_AVR::Storage test\r\n")); |
||||
test_write(); |
||||
test_readback(); |
||||
} |
||||
|
||||
void loop (void) { } |
||||
|
||||
AP_HAL_MAIN(); |
@ -1,5 +0,0 @@
@@ -1,5 +0,0 @@
|
||||
LIBRARIES += AP_Common |
||||
LIBRARIES += AP_Math |
||||
LIBRARIES += AP_Param |
||||
LIBRARIES += AP_Progmem |
||||
LIBRARIES += StorageManager |
@ -1,2 +0,0 @@
@@ -1,2 +0,0 @@
|
||||
BOARD = mega
|
||||
include ../../../../mk/apm.mk |
@ -1,58 +0,0 @@
@@ -1,58 +0,0 @@
|
||||
// -*- Mode: C++; c-basic-offset: 8; indent-tabs-mode: nil -*-
|
||||
|
||||
//
|
||||
// Example code for the AP_HAL AVRUARTDriver, based on FastSerial
|
||||
//
|
||||
// This code is placed into the public domain.
|
||||
//
|
||||
|
||||
#include <AP_Common/AP_Common.h> |
||||
#include <AP_Math/AP_Math.h> |
||||
#include <AP_Param/AP_Param.h> |
||||
#include <StorageManager/StorageManager.h> |
||||
#include <AP_Progmem/AP_Progmem.h> |
||||
|
||||
#include <AP_HAL/AP_HAL.h> |
||||
#include <AP_HAL_AVR/AP_HAL_AVR.h> |
||||
|
||||
#if CONFIG_HAL_BOARD == HAL_BOARD_APM2 |
||||
const AP_HAL::HAL& hal = AP_HAL_AVR_APM2; |
||||
#elif CONFIG_HAL_BOARD == HAL_BOARD_APM1 |
||||
const AP_HAL::HAL& hal = AP_HAL_AVR_APM1; |
||||
#endif |
||||
|
||||
void setup(void) |
||||
{ |
||||
//
|
||||
// HAL will start serial port at 115200.
|
||||
//
|
||||
|
||||
//
|
||||
// Test printing things
|
||||
//
|
||||
hal.console->print("test"); |
||||
hal.console->println(" begin"); |
||||
hal.console->println(1000); |
||||
hal.console->println(1000, 8); |
||||
hal.console->println(1000, 10); |
||||
hal.console->println(1000, 16); |
||||
hal.console->println_P(PSTR("progmem")); |
||||
int x = 3; |
||||
int *ptr = &x; |
||||
hal.console->printf("printf %d %u %#x %p %f %S\n", -1000, 1000, 1000, ptr, 1.2345, PSTR("progmem")); |
||||
hal.console->printf_P(PSTR("printf_P %d %u %#x %p %f %S\n"), -1000, 1000, 1000, ptr, 1.2345, PSTR("progmem")); |
||||
hal.console->println("done"); |
||||
} |
||||
|
||||
void loop(void) |
||||
{ |
||||
int c; |
||||
//
|
||||
// Perform a simple loopback operation.
|
||||
//
|
||||
c = hal.console->read(); |
||||
if (-1 != c) |
||||
hal.console->write(c); |
||||
} |
||||
|
||||
AP_HAL_MAIN(); |
@ -1,5 +0,0 @@
@@ -1,5 +0,0 @@
|
||||
LIBRARIES += AP_Common |
||||
LIBRARIES += AP_Math |
||||
LIBRARIES += AP_Param |
||||
LIBRARIES += AP_Progmem |
||||
LIBRARIES += StorageManager |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue