Subversion Repositories MK3Mag

Compare Revisions

Ignore whitespace Rev 31 → Rev 32

/trunk/analog.c
1,6 → 1,6
/*#######################################################################################
MK3Mag 3D-Magnet sensor
!!! THIS IS NOT FREE SOFTWARE !!!
!!! THIS IS NOT FREE SOFTWARE !!!
#######################################################################################*/
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Copyright (c) 05.2008 Holger Buss
8,15 → 8,15
// + Nur für den privaten Gebrauch
// + www.MikroKopter.com
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Die Portierung der Software (oder Teile davon) auf andere Systeme (ausser der Hardware von www.mikrokopter.de) ist nur
// + Die Portierung der Software (oder Teile davon) auf andere Systeme (ausser der Hardware von www.mikrokopter.de) ist nur
// + mit unserer Zustimmung zulässig
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Es gilt für das gesamte Projekt (Hardware, Software, Binärfiles, Sourcecode und Dokumentation),
// + dass eine Nutzung (auch auszugsweise) nur für den privaten (nicht-kommerziellen) Gebrauch zulässig ist.
// + Es gilt für das gesamte Projekt (Hardware, Software, Binärfiles, Sourcecode und Dokumentation),
// + dass eine Nutzung (auch auszugsweise) nur für den privaten (nicht-kommerziellen) Gebrauch zulässig ist.
// + AUSNAHME: Ein bei www.mikrokopter.de erworbener vorbestückter MK3Mag darf als Baugruppe auch in kommerziellen Systemen verbaut werden
// + Im Zweifelsfall bitte anfragen bei: info@mikrokopter.de
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Werden Teile des Quellcodes (mit oder ohne Modifikation) weiterverwendet oder veröffentlicht,
// + Werden Teile des Quellcodes (mit oder ohne Modifikation) weiterverwendet oder veröffentlicht,
// + unterliegen sie auch diesen Nutzungsbedingungen und diese Nutzungsbedingungen incl. Copyright müssen dann beiliegen
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Sollte die Software (auch auszugesweise) oder sonstige Informationen des MikroKopter-Projekts
29,19 → 29,19
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Die Funktion printf_P() unterliegt ihrer eigenen Lizenz und ist hiervon nicht betroffen
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Redistributions of source code (with or without modifications) must retain the above copyright notice,
// + Redistributions of source code (with or without modifications) must retain the above copyright notice,
// + this list of conditions and the following disclaimer.
// + * PORTING this software (or parts of it) to systems (other than hardware from www.mikrokopter.de) is NOT allowed
// + * Neither the name of the copyright holders nor the names of contributors may be used to endorse or promote products derived
// + from this software without specific prior written permission.
// + * The use of this project (hardware, software, binary files, sources and documentation) is only permittet
// + * The use of this project (hardware, software, binary files, sources and documentation) is only permittet
// + for non-commercial use (directly or indirectly)
// + Commercial use (for excample: selling of MikroKopters, selling of PCBs, assembly, ...) is only permitted
// + Commercial use (for excample: selling of MikroKopters, selling of PCBs, assembly, ...) is only permitted
// + with our written permission
// + Exception: A preassembled MK3Mag, purchased from www.mikrokopter.de may be used as a part of commercial systems
// + In case of doubt please contact: info@MikroKopter.de
// + * If sources or documentations are redistributet on other webpages, our webpage (http://www.MikroKopter.de) must be
// + clearly linked as origin
// + * If sources or documentations are redistributet on other webpages, our webpage (http://www.MikroKopter.de) must be
// + clearly linked as origin
// + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52,31 → 52,65
// + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// + POSSIBILITY OF SUCH DAMAGE.
// + POSSIBILITY OF SUCH DAMAGE.
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#include <util/delay.h>
#include "analog.h"
 
#include "main.h"
uint8_t AccPresent = 0;
 
//############################################################################
//Init ADC
void ADC_Init(void)
{
ADMUX = 0;
ADCSRA = 0x87;
ADMUX = 0;
ADCSRA |= 0x40; // Start Conversion
// The analog inputs have a VREF of 5V and a resolution of 10 bit (0...1024 counts)
// i.e. 4.88mV/Count
 
// set PortC 0,1,2,3 as input
DDRC &= ~((1<<DDC3)|(1<<DDC2)|(1<<DDC1)|(1<<DDC0));
// set PortC 0,1,2,3 as tri state
PORTC &= ~((1<<PORTC3)|(1<<PORTC2)|(1<<PORTC1)|(1<<PORTC0));
 
// port PD5 and PD6 control the current direction of the test coils of the sensors
DDRD |= ((1<<DDD5)|(1<<DDD6));
FLIP_LOW;
 
// disable internal reference voltage and right adjust bits in ADCW
ADMUX = 0x00;
// clear start conversion bit (ADSC = 0)
// disable ADC Auto Trigger Enable (ADATE = 0)
// disable interrupt (ADIE = 0)
ADCSRA &= ~((1<<ADSC)|(1<<ADATE)|(1<<ADIE));
// Enable ADC (ADEN = 1) with SYSCLK/128 (ADPS2 = 1, ADPS1 = 1, ADPS0 = 1) and clear ready flag (ADIF = 1)
ADCSRA |= ((1<<ADEN)|(1<<ADIF)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0));
ADMUX = 0x00; // select ADC0
ADCSRA |= (1<<ADSC); // start conversion
 
 
// Check if acceleration sensor is present
// The output of the LIS3L02AL (MK3MAG V1.0) and the LIS344ALH (MK3MAG V1.1) is Vdd/5 +/- 10% per 1g.
// The Vdd is 3.0V at this board therefore the sensitivity is 0.6V/g +/-10% that corresponds to 123 counts.
// The offsets at 0g is VDD/2 (1.5V) that is 307 counts.
// that yields to an ADC range of 184 to 430 counts.
 
// pullup PC2(AccX) and PC3 (AccY)
PORTC |= ((1<<PORTC3)|(1<<PORTC2));
_delay_ms(10.0);
// if ADC2 and ADC 3 is larger than 1000 counts (4.88V) no load is at the pins
if((ADC_GetValue(ADC2) > 1000) && (ADC_GetValue(ADC3) > 1000)) AccPresent = 0;
else AccPresent = 1;
// set port back to tristate
PORTC &= ~((1<<PORTC3)|(1<<PORTC2));
}
 
 
unsigned int MessAD(unsigned char channel)
uint16_t ADC_GetValue(ADChannel_t channel)
{
unsigned int messwert = 0;
ADMUX = channel;
ADCSRA |= 0x10; // Clear Ready-Bit
ADCSRA |= 0x40; // Start Conversion
while (((ADCSRA & 0x10) == 0));
messwert = ADCW;
return(messwert);
uint16_t value = 0;
ADMUX = channel; // set muxer bits
ADCSRA |= (1<<ADIF); // clear ready-flag
ADCSRA |= (1<<ADSC); // start conversion
while (((ADCSRA & (1<<ADIF)) == 0)); // wait for end of conversion
value = ADCW; // read adc result
return(value);
}
 
 
/trunk/analog.h
1,6 → 1,39
#ifndef _ANALOG_H_
#define _ANALOG_H_
 
extern void ADC_Init(void);
extern void GetAnalogWerte(void);
extern void AdConvert(void);
extern void FastADConvert(void);
extern unsigned int MessAD(unsigned char);
#include <inttypes.h>
#include <avr/io.h>
 
#define FLIP_HIGH PORTD |= ((1<<PORTD5)|(1<<PORTD6))
#define FLIP_LOW PORTD &= ~((1<<PORTD5)|(1<<PORTD6))
 
typedef enum
{
ADC0 = 0,
ADC1 = 1,
ADC2 = 2,
ADC3 = 3,
ADC4 = 4,
ADC5 = 5,
ADC6 = 6,
ADC7 = 7,
REF1V1 = 14,
AGND = 15
} ADChannel_t;
 
 
#define MAG_X ADC0
#define MAG_Y ADC1
#define MAG_Z ADC7
#define ACC_X ADC2
#define ACC_Y ADC3
#define ACC_Z ADC6
 
 
extern uint8_t AccPresent;
 
void ADC_Init(void);
uint16_t ADC_GetValue(ADChannel_t channel);
 
#endif // _ANALOG_H_
 
/trunk/led.c
0,0 → 1,67
/*#######################################################################################
MK3Mag 3D-Magnet sensor
!!! THIS IS NOT FREE SOFTWARE !!!
#######################################################################################*/
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Copyright (c) 05.2008 Holger Buss
// + Thanks to Ilja Fähnrich (P_Latzhalter)
// + Nur für den privaten Gebrauch
// + www.MikroKopter.com
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Die Portierung der Software (oder Teile davon) auf andere Systeme (ausser der Hardware von www.mikrokopter.de) ist nur
// + mit unserer Zustimmung zulässig
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Es gilt für das gesamte Projekt (Hardware, Software, Binärfiles, Sourcecode und Dokumentation),
// + dass eine Nutzung (auch auszugsweise) nur für den privaten (nicht-kommerziellen) Gebrauch zulässig ist.
// + AUSNAHME: Ein bei www.mikrokopter.de erworbener vorbestückter MK3Mag darf als Baugruppe auch in kommerziellen Systemen verbaut werden
// + Im Zweifelsfall bitte anfragen bei: info@mikrokopter.de
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Werden Teile des Quellcodes (mit oder ohne Modifikation) weiterverwendet oder veröffentlicht,
// + unterliegen sie auch diesen Nutzungsbedingungen und diese Nutzungsbedingungen incl. Copyright müssen dann beiliegen
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Sollte die Software (auch auszugesweise) oder sonstige Informationen des MikroKopter-Projekts
// + auf anderen Webseiten oder sonstigen Medien veröffentlicht werden, muss unsere Webseite "http://www.mikrokopter.de"
// + eindeutig als Ursprung verlinkt werden
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Keine Gewähr auf Fehlerfreiheit, Vollständigkeit oder Funktion
// + Benutzung auf eigene Gefahr
// + Wir übernehmen keinerlei Haftung für direkte oder indirekte Personen- oder Sachschäden
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Die Funktion printf_P() unterliegt ihrer eigenen Lizenz und ist hiervon nicht betroffen
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Redistributions of source code (with or without modifications) must retain the above copyright notice,
// + this list of conditions and the following disclaimer.
// + * PORTING this software (or parts of it) to systems (other than hardware from www.mikrokopter.de) is NOT allowed
// + * Neither the name of the copyright holders nor the names of contributors may be used to endorse or promote products derived
// + from this software without specific prior written permission.
// + * The use of this project (hardware, software, binary files, sources and documentation) is only permittet
// + for non-commercial use (directly or indirectly)
// + Commercial use (for excample: selling of MikroKopters, selling of PCBs, assembly, ...) is only permitted
// + with our written permission
// + Exception: A preassembled MK3Mag, purchased from www.mikrokopter.de may be used as a part of commercial systems
// + In case of doubt please contact: info@MikroKopter.de
// + * If sources or documentations are redistributet on other webpages, our webpage (http://www.MikroKopter.de) must be
// + clearly linked as origin
// + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// + POSSIBILITY OF SUCH DAMAGE.
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#include "led.h"
 
 
void LED_Init(void)
{
// Set PD7 as output
DDRD |= (1<<DDD7);
// set port pon to GND
PORTD &= ~((1<<PORTD7));
}
 
/trunk/led.h
0,0 → 1,12
#ifndef _LED_H_
#define _LED_H_
 
#include <avr/io.h>
 
#define LED_GRN_ON PORTD |= (1<<PORTD7)
#define LED_GRN_OFF PORTD &= ~(1<<PORTD7)
#define LED_GRN_TOGGLE PORTD ^= (1<<PORTD7)
 
void LED_Init(void);
 
#endif //_LED_H_
/trunk/main.c
1,6 → 1,6
/*#######################################################################################
MK3Mag 3D-Magnet sensor
!!! THIS IS NOT FREE SOFTWARE !!!
!!! THIS IS NOT FREE SOFTWARE !!!
#######################################################################################*/
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Copyright (c) 05.2008 Holger Buss
8,15 → 8,15
// + Nur für den privaten Gebrauch
// + www.MikroKopter.com
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Die Portierung der Software (oder Teile davon) auf andere Systeme (ausser der Hardware von www.mikrokopter.de) ist nur
// + Die Portierung der Software (oder Teile davon) auf andere Systeme (ausser der Hardware von www.mikrokopter.de) ist nur
// + mit unserer Zustimmung zulässig
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Es gilt für das gesamte Projekt (Hardware, Software, Binärfiles, Sourcecode und Dokumentation),
// + dass eine Nutzung (auch auszugsweise) nur für den privaten (nicht-kommerziellen) Gebrauch zulässig ist.
// + Es gilt für das gesamte Projekt (Hardware, Software, Binärfiles, Sourcecode und Dokumentation),
// + dass eine Nutzung (auch auszugsweise) nur für den privaten (nicht-kommerziellen) Gebrauch zulässig ist.
// + AUSNAHME: Ein bei www.mikrokopter.de erworbener vorbestückter MK3Mag darf als Baugruppe auch in kommerziellen Systemen verbaut werden
// + Im Zweifelsfall bitte anfragen bei: info@mikrokopter.de
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Werden Teile des Quellcodes (mit oder ohne Modifikation) weiterverwendet oder veröffentlicht,
// + Werden Teile des Quellcodes (mit oder ohne Modifikation) weiterverwendet oder veröffentlicht,
// + unterliegen sie auch diesen Nutzungsbedingungen und diese Nutzungsbedingungen incl. Copyright müssen dann beiliegen
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Sollte die Software (auch auszugesweise) oder sonstige Informationen des MikroKopter-Projekts
29,19 → 29,19
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Die Funktion printf_P() unterliegt ihrer eigenen Lizenz und ist hiervon nicht betroffen
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Redistributions of source code (with or without modifications) must retain the above copyright notice,
// + Redistributions of source code (with or without modifications) must retain the above copyright notice,
// + this list of conditions and the following disclaimer.
// + * PORTING this software (or parts of it) to systems (other than hardware from www.mikrokopter.de) is NOT allowed
// + * Neither the name of the copyright holders nor the names of contributors may be used to endorse or promote products derived
// + from this software without specific prior written permission.
// + * The use of this project (hardware, software, binary files, sources and documentation) is only permittet
// + * The use of this project (hardware, software, binary files, sources and documentation) is only permittet
// + for non-commercial use (directly or indirectly)
// + Commercial use (for excample: selling of MikroKopters, selling of PCBs, assembly, ...) is only permitted
// + Commercial use (for excample: selling of MikroKopters, selling of PCBs, assembly, ...) is only permitted
// + with our written permission
// + Exception: A preassembled MK3Mag, purchased from www.mikrokopter.de may be used as a part of commercial systems
// + In case of doubt please contact: info@MikroKopter.de
// + * If sources or documentations are redistributet on other webpages, our webpage (http://www.MikroKopter.de) must be
// + clearly linked as origin
// + * If sources or documentations are redistributet on other webpages, our webpage (http://www.MikroKopter.de) must be
// + clearly linked as origin
// + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52,105 → 52,186
// + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// + POSSIBILITY OF SUCH DAMAGE.
// + POSSIBILITY OF SUCH DAMAGE.
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#include <avr/interrupt.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
 
signed int OffsetN, OffsetR, OffsetZ;
signed int RawAccN = 0, RawAccR = 0, RawAccZ = 0;
signed int AccN = 0, AccR = 0, AccZ = 0;
signed int OffsetAccN = 0, OffsetAccR = 0, OffsetAccZ = 0;
signed int RawMagnet1a,RawMagnet1b; // raw AD-Data
signed int RawMagnet2a,RawMagnet2b;
signed int RawMagnet3a,RawMagnet3b;
signed int Xmin = 0, Xmax = 0, Ymin = 0, Ymax = 0, Zmin = 0, Zmax = 0;
signed int UncalMagnetN,UncalMagnetR,UncalMagnetZ; // Messwert-Delta ohne Offset- und Verstärker korrektur
signed int MagnetN,MagnetR,MagnetZ;
unsigned int PwmHeading = 0;
unsigned int PC_Connected = 0;
unsigned int Heading;
unsigned char ExternCalState = 0;
unsigned char AngleSource = 0;
unsigned char AccPresent = 0;
#include "main.h"
#define EE_KOMPATIBLE 1
uint16_t eeXmin EEMEM = 0;
uint16_t eeXmax EEMEM = 0;
uint16_t eeYmin EEMEM = 0;
uint16_t eeYmax EEMEM = 0;
uint16_t eeZmin EEMEM = 0;
uint16_t eeZmax EEMEM = 0;
uint16_t eeNoffset EEMEM = 0;
uint16_t eeRoffset EEMEM = 0;
uint16_t eeZoffset EEMEM = 0;
uint16_t eeKompatibel EEMEM = 0;
#include "timer0.h"
#include "twislave.h"
#include "led.h"
#include "analog.h"
#include "uart.h"
 
//############################################################################
//
void Wait(unsigned char dauer)
//############################################################################
 
AttitudeSource_t AttitudeSource = ATTITUDE_SOURCE_ACC;
Orientation_t Orientation = ORIENTATION_FC;
 
uint16_t Led_Timer = 0;
 
typedef struct
{
dauer = (unsigned char)TCNT0 + dauer;
while((TCNT0 - dauer) & 0x80);
}
int16_t Range;
int16_t Offset;
} Scaling_t;
 
typedef struct
{
Scaling_t MagX;
Scaling_t MagY;
Scaling_t MagZ;
Scaling_t AccX;
Scaling_t AccY;
Scaling_t AccZ;
} Calibration_t;
 
Calibration_t eeCalibration EEMEM; // calibration data in EEProm
Calibration_t Calibration; // calibration data in RAM
 
// magnet sensor variable
int16_t RawMagnet1a, RawMagnet1b; // raw magnet sensor data
int16_t RawMagnet2a, RawMagnet2b;
int16_t RawMagnet3a, RawMagnet3b;
int16_t UncalMagX, UncalMagY, UncalMagZ; // sensor signal difference without Scaling
int16_t MagX = 0, MagY = 0, MagZ = 0; // rescaled magnetic field readings
 
// acceleration sensor variables
int16_t RawAccX = 0, RawAccY = 0, RawAccZ = 0; // raw acceleration readings
int16_t AccX = 0, AccY = 0, AccZ = 0; // rescaled acceleration readings
int16_t AccAttitudeNick = 0, AccAttitudeRoll = 0; // nick and roll angle from acc
 
int16_t Heading = -1; // the current compass heading in deg
 
 
void CalcFields(void)
{
UncalMagnetN = (1 * UncalMagnetN + (RawMagnet1a - RawMagnet1b)) / 2;
UncalMagnetR = (1 * UncalMagnetR + (RawMagnet3a - RawMagnet3b)) / 2;
UncalMagnetZ = (1 * UncalMagnetZ + (RawMagnet2a - RawMagnet2b)) / 2;
UncalMagX = (RawMagnet1a - RawMagnet1b);
UncalMagY = (RawMagnet3a - RawMagnet3b);
UncalMagZ = (RawMagnet2a - RawMagnet2b);
 
OffsetN = (Xmin + Xmax) / 2;
OffsetR = (Ymin + Ymax) / 2;
OffsetZ = (Zmin + Zmax) / 2;
if(Calibration.MagX.Range != 0) MagX = (1024L * (int32_t)(UncalMagX - Calibration.MagX.Offset)) / (Calibration.MagX.Range);
else MagX = 0;
if(Calibration.MagY.Range != 0) MagY = (1024L * (int32_t)(UncalMagY - Calibration.MagY.Offset)) / (Calibration.MagY.Range);
else MagY = 0;
if(Calibration.MagY.Range != 0) MagZ = (1024L * (int32_t)(UncalMagZ - Calibration.MagZ.Offset)) / (Calibration.MagZ.Range);
else MagZ = 0;
 
MagnetN = (1024L * (long)(UncalMagnetN - OffsetN)) / (Xmax - Xmin);
MagnetR = (1024L * (long)(UncalMagnetR - OffsetR)) / (Ymax - Ymin);
MagnetZ = (1024L * (long)(UncalMagnetZ - OffsetZ)) / (Zmax - Zmin);
if(AccPresent)
{
AccX = (RawAccX - Calibration.AccX.Offset);
AccY = (RawAccY - Calibration.AccY.Offset);
AccZ = (Calibration.AccZ.Offset - RawAccZ);
 
#if (BOARD == 10) // the hardware 1.0 has the LIS3L02AL
// acc mode assumes orientation like FC
if(AccX > 136) AccAttitudeNick = -800;
else
if(AccX < -136) AccAttitudeNick = 800;
else AccAttitudeNick = (int16_t)(-1800.0 * asin((double) AccX / 138.0) / M_PI);
 
 
if(AccY > 136) AccAttitudeRoll = 800;
else
if(AccY < -136) AccAttitudeRoll = -800;
else AccAttitudeRoll = (int16_t)( 1800.0 * asin((double) AccY / 138.0) / M_PI);
 
#else // the hardware 1.1 has the LIS344ALH with a different axis definition (X -> -Y, Y -> X, Z -> Z)
// acc mode assumes orientation like FC
if(AccY > 136) AccAttitudeNick = 800;
else
if(AccY < -136) AccAttitudeNick = -800;
else AccAttitudeNick = (int16_t)( 1800.0 * asin((double) AccY / 138.0) / M_PI);
 
 
if(AccX > 136) AccAttitudeRoll = 800;
else
if(AccX < -136) AccAttitudeRoll = -800;
else AccAttitudeRoll = (int16_t)( 1800.0 * asin((double) AccX / 138.0) / M_PI);
#endif
}
}
 
 
void CalcHeading(void)
{
double nick_rad, roll_rad, Hx, Hy, Cx, Cy, Cz;
int heading;
heading = Heading;
if(!AngleSource)
{
if(AccN > 125) nick_rad = M_PI / 2;
else
if(AccN < -125) nick_rad = -M_PI / 2;
else
{
nick_rad = asin((double) AccN / 125.0);
}
if(AccR > 125) roll_rad = M_PI / 2;
else
if(AccR < -125) roll_rad = -M_PI / 2;
else
{
roll_rad = asin((double) AccR / 125.0);
}
ExternData.Winkel[0] = (nick_rad * 1800.0) / M_PI;
ExternData.Winkel[1] = (roll_rad * 1800.0) / M_PI;
ExternData.Orientation = 1;
}
else
{
nick_rad = ((double)ExternData.Winkel[0]) * M_PI / (double)(1800);
roll_rad = ((double)ExternData.Winkel[1]) * M_PI / (double)(1800);
}
double nick_rad, roll_rad, Hx, Hy, Cx = 0.0, Cy = 0.0, Cz = 0.0;
int16_t nick, roll;
int16_t heading = -1;
 
Cx = MagnetN;
Cy = MagnetR;
Cz = MagnetZ;
// blink code for normal operation
if(CheckDelay(Led_Timer))
{
LED_GRN_TOGGLE;
Led_Timer = SetDelay(500);
}
//MagX = 150;
//MagZ = 1000;
 
if(ExternData.Orientation == 1)
{
Cx = MagnetR;
Cy = -MagnetN;
Cz = MagnetZ;
}
switch(Orientation)
{
case ORIENTATION_NC:
Cx = MagX;
Cy = MagY;
Cz = MagZ;
break;
 
case ORIENTATION_FC:
// rotation of 90 deg compared to NC setup
Cx = MagY;
Cy = -MagX;
Cz = MagZ;
break;
}
 
// calculate nick and roll angle in rad
switch(AttitudeSource)
{
case ATTITUDE_SOURCE_I2C:
cli(); // stop interrupts
nick = I2C_WriteAttitude.Nick;
roll = I2C_WriteAttitude.Roll;
sei(); // start interrupts
break;
case ATTITUDE_SOURCE_UART:
cli(); // stop interrupts
nick = ExternData.Attitude[NICK];
roll = ExternData.Attitude[ROLL];
sei(); // start interrupts
break;
case ATTITUDE_SOURCE_ACC:
nick = AccAttitudeNick;
roll = AccAttitudeRoll;
break;
default:
nick_rad = 0;
roll_rad = 0;
break;
}
 
nick_rad = ((double)nick) * M_PI / (double)(1800.0);
roll_rad = ((double)roll) * M_PI / (double)(1800.0);
 
// nick_rad = 0;
// roll_rad = 0;
 
// calculate attitude correction
Hx = Cx * cos(nick_rad) - Cz * sin(nick_rad);
Hy = Cy * cos(roll_rad) + Cz * sin(roll_rad);
 
DebugOut.Analog[27] = (int16_t)Hx;
DebugOut.Analog[28] = (int16_t)Hy;
 
// calculate Heading
heading = (int16_t)((180.0 * atan2(Hy, Hx)) / M_PI);
// atan2 returns angular range from -180 deg to 180 deg in counter clockwise notation
// but the compass course is defined in a range from 0 deg to 360 deg clockwise notation.
if (heading < 0) heading = -heading;
else heading = 360 - heading;
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
/*
Hx = Cx * (double)cos(nick_rad) +
Cy * (double)sin(nick_rad) * (double)sin(roll_rad) -
Cz * (double)sin(nick_rad) * (double)cos(roll_rad);
157,7 → 238,6
Hy = Cy * (double)cos(roll_rad) +
Cz * (double)sin(roll_rad);
if(Hx == 0 && Hy < 0) heading = 90;
else if(Hx == 0 && Hy > 0) heading = 270;
166,226 → 246,267
else if(Hx > 0 && Hy > 0) heading = 360 - (atan(Hy / Hx) * 180.0) / M_PI;
 
if(abs(heading) < 361) Heading = heading;
PwmHeading = Heading + 10;
*/
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
cli(); // stop interrupts
if(abs(heading) < 361) Heading = heading;
else (Heading = -1);
sei(); // start interrupts
}
 
 
void Calibrate(void)
{
unsigned char cal;
if(I2C_WriteCal.CalByte) cal = I2C_WriteCal.CalByte;
else
if(ExternCalState) cal = ExternCalState;
else cal = ExternData.CalState;
uint8_t cal;
static uint8_t calold = 0;
static int16_t Xmin = 0, Xmax = 0, Ymin = 0, Ymax = 0, Zmin = 0, Zmax = 0;
static uint8_t blinkcount = 0;
static uint8_t invert_blinking = 0;
// check both sources of communication for calibration request
if(I2C_WriteCal.CalByte) cal = I2C_WriteCal.CalByte;
else cal = ExternData.CalState;
 
switch(cal)
{
case 0:
LED_ON;
break;
case 1:
Xmin = 10000;
Xmax = -10000;
Ymin = 10000;
Ymax = -10000;
Zmin = 10000;
Zmax = -10000;
OffsetAccN = RawAccN;
OffsetAccR = RawAccR;
OffsetAccZ = RawAccZ;
LED_OFF;
break;
case 2:
LED_ON; // find Min and Max of the X- and Y-Sensors
if(UncalMagnetN < Xmin) Xmin = UncalMagnetN;
if(UncalMagnetN > Xmax) Xmax = UncalMagnetN;
if(UncalMagnetR < Ymin) Ymin = UncalMagnetR;
if(UncalMagnetR > Ymax) Ymax = UncalMagnetR;
break;
case 3:
LED_OFF;
break;
case 4:
LED_ON; // find Min and Max of the Z-Sensor
if(UncalMagnetZ < Zmin) Zmin = UncalMagnetZ;
if(UncalMagnetZ > Zmax) Zmax = UncalMagnetZ;
break;
case 5:
LED_OFF; // Save values
if((Xmax - Xmin) > 150 && (Ymax - Ymin) > 150 && (Zmax - Zmin) > 150)
{
eeprom_write_word(&eeXmin, Xmin);
eeprom_write_word(&eeXmax, Xmax);
eeprom_write_word(&eeYmin, Ymin);
eeprom_write_word(&eeYmax, Ymax);
eeprom_write_word(&eeZmin, Zmin);
eeprom_write_word(&eeZmax, Zmax);
eeprom_write_word(&eeNoffset, OffsetAccN);
eeprom_write_word(&eeRoffset, OffsetAccR);
eeprom_write_word(&eeZoffset, OffsetAccZ);
Delay_ms(2000);
}
ExternCalState = 0;
LED_ON;
break;
}
 
if(cal > 5) cal = 0;
// blink code for current calibration state
if(cal)
{
if(CheckDelay(Led_Timer) || (cal != calold))
{
if(blinkcount & 0x01) if(invert_blinking) LED_GRN_ON; else LED_GRN_OFF;
else if(invert_blinking) LED_GRN_OFF; else LED_GRN_ON;
 
// end of blinkcount sequence
if((blinkcount + 1 ) >= (2 * cal))
{
blinkcount = 0;
Led_Timer = SetDelay(1000);
}
else
{
blinkcount++;
Led_Timer = SetDelay(170);
}
}
}
else
{
if(invert_blinking) LED_GRN_ON; else LED_GRN_OFF;
}
 
// calibration state machine
switch(cal)
{
case 1: // 1st step of calibration
// initialize ranges
// used to change the orientation of the MK3MAG in the horizontal plane
Xmin = 10000;
Xmax = -10000;
Ymin = 10000;
Ymax = -10000;
Zmin = 10000;
Zmax = -10000;
Calibration.AccX.Offset = RawAccX;
Calibration.AccY.Offset = RawAccY;
Calibration.AccZ.Offset = RawAccZ;
invert_blinking = 0;
break;
 
case 2: // 2nd step of calibration
// find Min and Max of the X- and Y-Sensors during rotation in the horizontal plane
if(UncalMagX < Xmin) Xmin = UncalMagX;
if(UncalMagX > Xmax) Xmax = UncalMagX;
if(UncalMagY < Ymin) Ymin = UncalMagY;
if(UncalMagY > Ymax) Ymax = UncalMagY;
invert_blinking = 1;
break;
 
case 3: // 3rd step of calibration
// used to change the orientation of the MK3MAG vertical to the horizontal plane
invert_blinking = 0;
break;
 
case 4:
// find Min and Max of the Z-Sensor
if(UncalMagZ < Zmin) Zmin = UncalMagZ;
if(UncalMagZ > Zmax) Zmax = UncalMagZ;
invert_blinking = 1;
break;
 
case 5:
// Save values
if(cal != calold) // avoid continously writing of eeprom!
{
Calibration.MagX.Range = Xmax - Xmin;
Calibration.MagX.Offset = (Xmin + Xmax) / 2;
Calibration.MagY.Range = Ymax - Ymin;
Calibration.MagY.Offset = (Ymin + Ymax) / 2;
Calibration.MagZ.Range = Zmax - Zmin;
Calibration.MagZ.Offset = (Zmin + Zmax) / 2;
if((Calibration.MagX.Range > 150) && (Calibration.MagY.Range > 150) && (Calibration.MagZ.Range > 150))
{
// indicate write process by setting the led
LED_GRN_ON;
eeprom_write_block(&Calibration, &eeCalibration, sizeof(Calibration));
Led_Timer = SetDelay(2000);
// reset blinkcode
blinkcount = 0;
}
}
invert_blinking = 0;
break;
 
default:
break;
}
calold = cal;
}
 
 
void SetDebugValues(void)
{
DebugOut.Analog[0] = MagnetN;
DebugOut.Analog[1] = MagnetR;
DebugOut.Analog[2] = MagnetZ;
DebugOut.Analog[3] = UncalMagnetN;
DebugOut.Analog[4] = UncalMagnetR;
DebugOut.Analog[5] = UncalMagnetZ;
DebugOut.Analog[6] = ExternData.Winkel[0];
DebugOut.Analog[7] = ExternData.Winkel[1];
DebugOut.Analog[8] = Xmin;
DebugOut.Analog[9] = Xmax;
DebugOut.Analog[10] = Ymin;
DebugOut.Analog[11] = Ymax;
DebugOut.Analog[12] = Zmin;
DebugOut.Analog[13] = Zmax;
DebugOut.Analog[14] = Heading;
if(!ExternCalState) DebugOut.Analog[15] = ExternData.CalState;
else DebugOut.Analog[15] = ExternCalState;
DebugOut.Analog[16] = ExternData.UserParameter[0];
DebugOut.Analog[17] = ExternData.UserParameter[1];
DebugOut.Analog[18] = AccN;
DebugOut.Analog[19] = AccR;
DebugOut.Analog[20] = AccZ;
DebugOut.Analog[21] = RawAccN;
DebugOut.Analog[22] = RawAccR;
DebugOut.Analog[23] = RawAccZ;
DebugOut.Analog[24] = OffsetAccN;
DebugOut.Analog[25] = OffsetAccR;
DebugOut.Analog[26] = OffsetAccZ;
DebugOut.Analog[0] = MagX;
DebugOut.Analog[1] = MagY;
DebugOut.Analog[2] = MagZ;
DebugOut.Analog[3] = UncalMagX;
DebugOut.Analog[4] = UncalMagY;
DebugOut.Analog[5] = UncalMagZ;
switch(AttitudeSource)
{
case ATTITUDE_SOURCE_ACC:
DebugOut.Analog[6] = AccAttitudeNick;
DebugOut.Analog[7] = AccAttitudeRoll;
break;
 
case ATTITUDE_SOURCE_UART:
DebugOut.Analog[6] = ExternData.Attitude[NICK];
DebugOut.Analog[7] = ExternData.Attitude[ROLL];
break;
 
 
case ATTITUDE_SOURCE_I2C:
DebugOut.Analog[6] = I2C_WriteAttitude.Nick;
DebugOut.Analog[7] = I2C_WriteAttitude.Roll;
break;
}
DebugOut.Analog[8] = Calibration.MagX.Offset;
DebugOut.Analog[9] = Calibration.MagX.Range;
DebugOut.Analog[10] = Calibration.MagY.Offset;
DebugOut.Analog[11] = Calibration.MagY.Range;
DebugOut.Analog[12] = Calibration.MagZ.Offset;
DebugOut.Analog[13] = Calibration.MagZ.Range;
DebugOut.Analog[14] = ExternData.CalState;
DebugOut.Analog[15] = Heading;
DebugOut.Analog[16] = ExternData.UserParam[0];
DebugOut.Analog[17] = ExternData.UserParam[1];
DebugOut.Analog[18] = AccX;
DebugOut.Analog[19] = AccY;
DebugOut.Analog[20] = AccZ;
DebugOut.Analog[21] = RawAccX;
DebugOut.Analog[22] = RawAccY;
DebugOut.Analog[23] = RawAccZ;
DebugOut.Analog[24] = Calibration.AccX.Offset;
DebugOut.Analog[25] = Calibration.AccY.Offset;
DebugOut.Analog[26] = Calibration.AccZ.Offset;
DebugOut.Analog[29] = AttitudeSource;
}
 
void AccMeasurement(void)
{
if(AccPresent)
{
RawAccN = (RawAccN + (signed int)MessAD(2))/2;
RawAccR = (RawAccR + (signed int)MessAD(3))/2;
RawAccZ = (RawAccZ + (signed int)MessAD(6))/2;
}
else
{
RawAccN = 0;
RawAccR = 0;
RawAccZ = 0;
}
AccR = (((signed int) RawAccN - OffsetAccN) + AccR * 7) / 8;
AccN = (((signed int) RawAccR - OffsetAccR) + AccN * 7) / 8;
AccZ = ((OffsetAccZ - (signed int) RawAccZ) + AccZ * 7) / 8;
if(AccPresent)
{
RawAccX = (RawAccX + (int16_t)ADC_GetValue(ACC_X))/2;
RawAccY = (RawAccY + (int16_t)ADC_GetValue(ACC_Y))/2;
RawAccZ = (RawAccZ + (int16_t)ADC_GetValue(ACC_Z))/2;
}
else
{
RawAccX = 0;
RawAccY = 0;
RawAccZ = 0;
}
}
 
 
//############################################################################
//Hauptprogramm
int main (void)
//############################################################################
{
char j3_state = 0,debounce = 1;
DDRC = 0x00;
PORTC = 0x0c;
DDRD = 0xfe;
PORTD = 0xA8;
DDRB = 0x04;
PORTB = 0x35;
LED_ON;
// reset input pullup
DDRC &=~((1<<DDC6));
PORTC |= (1<<PORTC6);
 
UART_Init();
Timer0_Init();
LED_Init();
TIMER0_Init();
USART0_Init();
ADC_Init();
InitIC2_Slave();
sei();//Globale Interrupts Einschalten
Debug_Timer = SetDelay(100); // Sendeintervall
if(eeprom_read_word(&eeKompatibel) == EE_KOMPATIBLE)
{
Xmin = eeprom_read_word(&eeXmin);
Xmax = eeprom_read_word(&eeXmax);
Ymin = eeprom_read_word(&eeYmin);
Ymax = eeprom_read_word(&eeYmax);
Zmin = eeprom_read_word(&eeZmin);
Zmax = eeprom_read_word(&eeZmax);
OffsetAccN = eeprom_read_word(&eeNoffset);
OffsetAccR = eeprom_read_word(&eeRoffset);
OffsetAccZ = eeprom_read_word(&eeZoffset);
}
else
{
// UartPrint("not calibrated\n");
};
I2C_Init();
 
VersionInfo.Hauptversion = VERSION_HAUPTVERSION;
VersionInfo.Nebenversion = VERSION_NEBENVERSION;
VersionInfo.PCKompatibel = 7;
ExternData.Orientation = 0;
sei(); // enable globale interrupts
 
if(AccPresent)
{
USART0_Print("ACC present\n");
}
 
LED_GRN_ON;
 
Debug_Timer = SetDelay(200);
Led_Timer = SetDelay(200);
 
// read calibration info from eeprom
eeprom_read_block(&Calibration, &eeCalibration, sizeof(Calibration));
 
ExternData.CalState = 0;
I2C_WriteCal.CalByte = 0;
ExternCalState = 0;
Delay_ms(10);
RawAccR = MessAD(2);
RawAccN = MessAD(3);
if(RawAccR > 1000 && RawAccN > 1000) AccPresent = 0; else AccPresent = 1;
if(AccPresent)
{
// UartPrint("ACC\n");
}
PORTC &= ~0x0c;
Delay_ms(100);
if(!PIN_J3) { ExternCalState++; j3_state = 1;}
RawAccR = MessAD(2);
RawAccN = MessAD(3);
RawAccZ = MessAD(6);
UART_InterruptEnable();
 
 
// main loop
while (1)
{
FLIP_LOW;
Delay_ms(2);
RawMagnet1a = MessAD(0);
RawMagnet2a = -MessAD(1);
RawMagnet3a = MessAD(7);
AccMeasurement();
Delay_ms(1);
{
FLIP_LOW;
Delay_ms(2);
RawMagnet1a = ADC_GetValue(MAG_X);
RawMagnet2a = -ADC_GetValue(MAG_Y);
RawMagnet3a = ADC_GetValue(MAG_Z);
AccMeasurement();
Delay_ms(1);
 
FLIP_HIGH;
Delay_ms(2);
RawMagnet1b = MessAD(0);
RawMagnet2b = -MessAD(1);
RawMagnet3b = MessAD(7);
AccMeasurement();
Delay_ms(1);
FLIP_HIGH;
Delay_ms(2);
RawMagnet1b = ADC_GetValue(MAG_X);
RawMagnet2b = -ADC_GetValue(MAG_Y);
RawMagnet3b = ADC_GetValue(MAG_Z);
AccMeasurement();
Delay_ms(1);
 
CalcFields();
if(ExternData.CalState || I2C_WriteCal.CalByte || ExternCalState) Calibrate();
else CalcHeading();
BearbeiteRxDaten();
CalcFields();
 
if(ExternCalState)
if(!debounce--)
{
if(!PIN_J3) { if(!j3_state) ExternCalState++; j3_state = 1;} else j3_state = 0;
debounce = 20;
}
if(ExternData.CalState || I2C_WriteCal.CalByte) Calibrate();
else CalcHeading();
 
if(PC_Connected)
{
DDRD |= 0x02; // TXD-Portpin
UCR |= (1 << TXEN);
DatenUebertragung();
PC_Connected--;
}
else
{
UCR &= ~(1 << TXEN);
DDRD &= ~0x02; // TXD-Portpin
}
} // while(1)
// check data from USART
USART0_ProcessRxData();
 
if(NC_Connected) NC_Connected--;
if(FC_Connected) FC_Connected--;
// fall back to attitude estimation from acc sensor if NC or FC does'nt send attittude data
if(!FC_Connected && ! NC_Connected)
{
AttitudeSource = ATTITUDE_SOURCE_ACC;
Orientation = ORIENTATION_FC;
}
 
if(PC_Connected)
{
USART0_EnableTXD();
USART0_TransmitTxData();
PC_Connected--;
}
else
{
USART0_DisableTXD();
}
} // while(1)
}
 
/trunk/main.h
1,79 → 1,36
#ifndef _MAIN_H
#define _MAIN_H
#ifndef _MAIN_H_
#define _MAIN_H_
 
 
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>
#include <avr/boot.h>
#include <avr/wdt.h>
#include <avr/eeprom.h>
#include <inttypes.h>
 
#include "twislave.h"
#include "old_macros.h"
#include "analog.h"
#include "uart.h"
#include "timer0.h"
 
typedef enum
{
ATTITUDE_SOURCE_I2C,
ATTITUDE_SOURCE_UART,
ATTITUDE_SOURCE_ACC
} AttitudeSource_t;
 
#if defined(__AVR_ATmega8__)
# define OC1 PB1
# define DDROC DDRB
# define OCR OCR1A
# define PWM10 WGM10
# define PWM11 WGM11
#endif
 
#define SYSCLK 8000000L //Quarz Frequenz in Hz
typedef enum
{
ORIENTATION_NC = 0,
ORIENTATION_FC = 1
} Orientation_t;
 
#define INT0_ENABLE GIMSK |= 0x40
#define INT0_DISABLE GIMSK &= ~0x40
#define TIM0_START TIMSK0 |= _BV(TOIE0)
#define TIM0_STOPP TIMSK0 &= ~_BV(TOIE0)
 
#define ICP_INT_ENABLE TIMSK0 |= 0x20
#define ICP_INT_DISABLE TIMSK0 &= ~0x20
#define TIMER1_INT_ENABLE TIMSK0 |= 0x04
#define TIMER1_INT_DISABLE TIMSK0 &= ~0x04
#define TIMER2_INT_ENABLE TIMSK0 |= 0x40
#define TIMER2_INT_DISABLE TIMSK0 &= ~0x40
#define INT0_POS_FLANKE MCUCR |= 0x01
#define INT0_ANY_FLANKE MCUCR |= 0x01
#define INT0_NEG_FLANKE MCUCR &= ~0x01
#define CLR_INT0_FLAG GIFR &= ~0x40
#define INIT_INT0_FLANKE MCUCR &= ~0x03; MCUCR |= 0x02;
#define TIMER0_PRESCALER TCCR0
#define ICP_POS_FLANKE TCCR1B |= (1<<ICES1)
#define ICP_NEG_FLANKE TCCR1B &= ~(1<<ICES1)
extern int16_t Heading;
 
#define LED_ON PORTD |= 0x80
#define LED_OFF PORTD &= ~0x80
#define FLIP_HIGH PORTD |= 0x60
#define FLIP_LOW PORTD &= ~0x60
#define PIN_J3 (PIND & 0x08)
extern AttitudeSource_t AttitudeSource;
extern Orientation_t Orientation;
 
extern unsigned int PwmHeading;
extern unsigned int PC_Connected;
extern unsigned int Heading;
extern signed int MagnetN,MagnetR,MagnetZ;
extern signed int RawAccN, RawAccR, RawAccZ;
extern signed int AccN, AccR, AccZ;
extern signed int OffsetAccN, OffsetAccR, OffsetAccZ;
extern unsigned char AngleSource;
extern uint16_t eeXmin EEMEM;
extern uint16_t eeXmax EEMEM;
extern uint16_t eeYmin EEMEM;
extern uint16_t eeYmax EEMEM;
extern uint16_t eeZmin EEMEM;
extern uint16_t eeZmax EEMEM;
extern int16_t MagX, MagY, MagZ;
 
void SetDebugValues(void);
 
#endif //_MAIN_H
#endif //_MAIN_H_
 
 
 
/trunk/makefile
1,9 → 1,14
#--------------------------------------------------------------------
# MCU name
MCU = atmega168
F_CPU = 8000000
#-------------------------------------------------------------------
HAUPT_VERSION = 0
NEBEN_VERSION = 16
BOARD = 10
#BOARD = 11
VERSION_MAJOR = 0
VERSION_MINOR = 18
 
VERSION_COMPATIBLE = 8 # PC-Kompatibilität
#-------------------------------------------------------------------
 
# Output format. (can be srec, ihex, binary)
10,7 → 15,7
FORMAT = ihex
 
# Target file name (without extension).
TARGET = MK3Mag_MEGA168_V$(HAUPT_VERSION)_$(NEBEN_VERSION)
TARGET = MK3Mag_MEGA168_V$(VERSION_MAJOR)_$(VERSION_MINOR)
 
# Optimization level, can be [0, 1, 2, 3, s]. 0 turns off optimization.
# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
18,20 → 23,10
 
##########################################################################################################
# List C source files here. (C dependencies are automatically generated.)
SRC = main.c uart.c timer0.c analog.c twislave.c
#printf_P.c
SRC = main.c uart.c timer0.c analog.c twislave.c led.c
##########################################################################################################
 
# If there is more than one source file, append them above, or modify and
# uncomment the following:
#SRC += foo.c bar.c
 
# You can also wrap lines by appending a backslash to the end of the line:
#SRC += baz.c \
#xyzzy.c
 
 
 
# List Assembler source files here.
# Make them always end in a capital .S. Files ending in a lowercase .s
# will not be considered source files but generated files (assembler
47,6 → 42,8
EXTRAINCDIRS =
 
 
CDEFS = -DF_CPU=$(F_CPU)UL
 
# Optional compiler flags.
# -g: generate debugging information (for GDB, or for COFF conversion)
# -O*: optimization level
68,9 → 65,9
#CFLAGS += -std=gnu89
#CFLAGS += -std=c99
CFLAGS += -std=gnu99
CFLAGS += $(CDEFS)
CFLAGS += -DVERSION_MAJOR=$(VERSION_MAJOR) -DVERSION_MINOR=$(VERSION_MINOR) -DVERSION_COMPATIBLE=$(VERSION_COMPATIBLE) -DBOARD=$(BOARD)
 
CFLAGS += -DVERSION_HAUPTVERSION=$(HAUPT_VERSION) -DVERSION_NEBENVERSION=$(NEBEN_VERSION)
 
ifeq ($(AVR_CTRL_PLATINE), 1)
CFLAGS += -DAVR_CTRL_PLATINE=$(AVR_CTRL_PLATINE)
endif
/trunk/timer0.c
1,6 → 1,6
/*#######################################################################################
MK3Mag 3D-Magnet sensor
!!! THIS IS NOT FREE SOFTWARE !!!
!!! THIS IS NOT FREE SOFTWARE !!!
#######################################################################################*/
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Copyright (c) 05.2008 Holger Buss
8,15 → 8,15
// + Nur für den privaten Gebrauch
// + www.MikroKopter.com
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Die Portierung der Software (oder Teile davon) auf andere Systeme (ausser der Hardware von www.mikrokopter.de) ist nur
// + Die Portierung der Software (oder Teile davon) auf andere Systeme (ausser der Hardware von www.mikrokopter.de) ist nur
// + mit unserer Zustimmung zulässig
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Es gilt für das gesamte Projekt (Hardware, Software, Binärfiles, Sourcecode und Dokumentation),
// + dass eine Nutzung (auch auszugsweise) nur für den privaten (nicht-kommerziellen) Gebrauch zulässig ist.
// + Es gilt für das gesamte Projekt (Hardware, Software, Binärfiles, Sourcecode und Dokumentation),
// + dass eine Nutzung (auch auszugsweise) nur für den privaten (nicht-kommerziellen) Gebrauch zulässig ist.
// + AUSNAHME: Ein bei www.mikrokopter.de erworbener vorbestückter MK3Mag darf als Baugruppe auch in kommerziellen Systemen verbaut werden
// + Im Zweifelsfall bitte anfragen bei: info@mikrokopter.de
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Werden Teile des Quellcodes (mit oder ohne Modifikation) weiterverwendet oder veröffentlicht,
// + Werden Teile des Quellcodes (mit oder ohne Modifikation) weiterverwendet oder veröffentlicht,
// + unterliegen sie auch diesen Nutzungsbedingungen und diese Nutzungsbedingungen incl. Copyright müssen dann beiliegen
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Sollte die Software (auch auszugesweise) oder sonstige Informationen des MikroKopter-Projekts
29,19 → 29,19
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Die Funktion printf_P() unterliegt ihrer eigenen Lizenz und ist hiervon nicht betroffen
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Redistributions of source code (with or without modifications) must retain the above copyright notice,
// + Redistributions of source code (with or without modifications) must retain the above copyright notice,
// + this list of conditions and the following disclaimer.
// + * PORTING this software (or parts of it) to systems (other than hardware from www.mikrokopter.de) is NOT allowed
// + * Neither the name of the copyright holders nor the names of contributors may be used to endorse or promote products derived
// + from this software without specific prior written permission.
// + * The use of this project (hardware, software, binary files, sources and documentation) is only permittet
// + * The use of this project (hardware, software, binary files, sources and documentation) is only permittet
// + for non-commercial use (directly or indirectly)
// + Commercial use (for excample: selling of MikroKopters, selling of PCBs, assembly, ...) is only permitted
// + Commercial use (for excample: selling of MikroKopters, selling of PCBs, assembly, ...) is only permitted
// + with our written permission
// + Exception: A preassembled MK3Mag, purchased from www.mikrokopter.de may be used as a part of commercial systems
// + In case of doubt please contact: info@MikroKopter.de
// + * If sources or documentations are redistributet on other webpages, our webpage (http://www.MikroKopter.de) must be
// + clearly linked as origin
// + * If sources or documentations are redistributet on other webpages, our webpage (http://www.MikroKopter.de) must be
// + clearly linked as origin
// + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52,77 → 52,119
// + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// + POSSIBILITY OF SUCH DAMAGE.
// + POSSIBILITY OF SUCH DAMAGE.
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include "main.h"
volatile unsigned int CountMilliseconds = 0;
volatile unsigned char Timer0Overflow;
unsigned int I2C_Timeout = 0;
unsigned int SIO_Timeout = 0;
 
enum {
STOP = 0,
CK = 1,
CK8 = 2,
CK64 = 3,
CK256 = 4,
CK1024 = 5,
T0_FALLING_EDGE = 6,
T0_RISING_EDGE = 7
};
volatile uint16_t CountMilliseconds = 0;
volatile uint16_t I2C_Timeout = 0;
 
 
SIGNAL(SIG_OVERFLOW0)
/*****************************************************/
/* Initialize Timer 0 */
/*****************************************************/
void TIMER0_Init(void)
{
static unsigned char cnt;
static unsigned int cmps_cnt;
TCNT0 -= 101; // reload
Timer0Overflow++;
// set PB2 as output for the PWM used to signal compass heading
DDRB |= (1<<DDB2);
PORTB &= ~(1<<PORTB2);
 
if(++cmps_cnt == 380)
{
PORTB |= 0x04;
cmps_cnt = 0;
}
else
if(cmps_cnt == PwmHeading)
{
PORTB &= ~0x04;
}
if(!--cnt)
{
cnt = 10;
CountMilliseconds += 1;
if(I2C_Timeout) I2C_Timeout--;
if(SIO_Timeout) SIO_Timeout--;
}
 
// Timer/Counter 0 Control Register A
 
// Normal Timer Counter Mode (Bits WGM02 = 0, WGM01 = 0, WGM00 = 0)
// OC0A disconnected (Bits COM0A1 = 0, COM0A0 = 0)
// OC0B disconnected (Bits COM0B1 = 0, COM0B0 = 0)
TCCR0A &= ~((1<<COM0A1)|(1<<COM0A0)|(1<<COM0B1)|(1<<COM0B0)|(1<<WGM01)|(1<<WGM00));
 
// Timer/Counter 0 Control Register B
 
// set clock devider for timer 0 to SYSKLOCK/8 = 8MHz / 8 = 1MHz
// i.e. the timer increments from 0x00 to 0xFF with an update rate of 2.5 MHz
// hence the timer overflow interrupt frequency is 2.5 MHz / 256 = 9.765 kHz
 
// divider 8 (Bits CS02 = 0, CS01 = 1, CS00 = 0)
TCCR0B &= ~((1<<FOC0A)|(1<<FOC0B)|(1<<WGM02)|(1<<CS02));
TCCR0B = (1<<CS01)|(0<<CS00);
 
// init Timer/Counter 0 Register
TCNT0 = 0;
 
// Timer/Counter 0 Interrupt Mask Register
// enable timer overflow interrupt only
TIMSK0 &= ~((1<<OCIE0B)|(1<<OCIE0A));
TIMSK0 |= (1<<TOIE0);
 
}
 
 
void Timer0_Init(void)
// -----------------------------------------------------------------------
ISR(TIMER0_OVF_vect)
{
TCCR0B = TIMER_TEILER; // Starten des Timers
// TCNT0 = 100; // reload
TIM0_START;
TIMER2_INT_ENABLE;
static uint8_t cnt;
static uint16_t cmps_cnt;
 
// reload timer register so that overflow occurs after 100 increments at 1 MHz
// resulting in a calling rate of this ISR of 10kHz or 0.1 ms.
TCNT0 -= 101;
 
// disable PWM when bad compass heading value
if(Heading < 0)
{
PORTB &= ~(1<<PORTB2);
cmps_cnt = 0;
}
else
{
// if a periode of 38.0 ms is over
if(++cmps_cnt >= 380)
{
// set PWM out to high
PORTB |= (1<<PORTB2);
// reset periode counter
cmps_cnt = 0;
}
// if the delay in 0.1 ms is equal to Heading + 10
else if(cmps_cnt >= (Heading + 10))
{
// set PWM out to low
PORTB &= ~(1<<PORTB2);
}
}
 
if(!--cnt)
{
// every 10th run (1kHz or 1ms)
cnt = 10;
CountMilliseconds++;
if(I2C_Timeout) I2C_Timeout--;
}
}
 
 
unsigned int SetDelay(unsigned int t)
// -----------------------------------------------------------------------
uint16_t SetDelay (uint16_t t)
{
return(CountMilliseconds + t - 1);
return(CountMilliseconds + t - 1);
}
 
char CheckDelay (unsigned int t)
// -----------------------------------------------------------------------
int8_t CheckDelay(uint16_t t)
{
return(((t - CountMilliseconds) & 0x8000) >> 8);
return(((t - CountMilliseconds) & 0x8000) >> 8); // check sign bit
}
 
void Delay_ms(unsigned int w)
// -----------------------------------------------------------------------
void Delay_ms(uint16_t wait)
{
unsigned int akt;
akt = SetDelay(w);
while (!CheckDelay(akt));
uint16_t t_stop;
t_stop = SetDelay(wait);
while (!CheckDelay(t_stop));
}
 
 
 
 
/trunk/timer0.h
1,16 → 1,22
#define TIMER_TEILER CK8
//#define TIMER_RELOAD_VALUE 125
#ifndef _TIMER0_H
#define _TIMER0_H
 
#include <inttypes.h>
 
extern volatile unsigned int CountMilliseconds;
extern volatile unsigned char Timer0Overflow;
extern unsigned int I2C_Timeout;
extern unsigned int SIO_Timeout;
extern volatile uint16_t CountMilliseconds;
extern volatile uint16_t I2C_Timeout;
 
 
void Timer1_Init(void);
void Delay_ms(unsigned int);
unsigned int SetDelay (unsigned int t);
char CheckDelay (unsigned int t);
void Timer0_Init(void);
void TIMER0_Init(void);
uint16_t SetDelay (uint16_t t);
int8_t CheckDelay(uint16_t t);
void Delay_ms(uint16_t wait);
 
 
#endif //_TIMER0_H
 
 
 
 
 
 
/trunk/twislave.c
1,6 → 1,6
/*#######################################################################################
MK3Mag 3D-Magnet sensor
!!! THIS IS NOT FREE SOFTWARE !!!
!!! THIS IS NOT FREE SOFTWARE !!!
#######################################################################################*/
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Copyright (c) 05.2008 Holger Buss
8,15 → 8,15
// + Nur für den privaten Gebrauch
// + www.MikroKopter.com
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Die Portierung der Software (oder Teile davon) auf andere Systeme (ausser der Hardware von www.mikrokopter.de) ist nur
// + Die Portierung der Software (oder Teile davon) auf andere Systeme (ausser der Hardware von www.mikrokopter.de) ist nur
// + mit unserer Zustimmung zulässig
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Es gilt für das gesamte Projekt (Hardware, Software, Binärfiles, Sourcecode und Dokumentation),
// + dass eine Nutzung (auch auszugsweise) nur für den privaten (nicht-kommerziellen) Gebrauch zulässig ist.
// + Es gilt für das gesamte Projekt (Hardware, Software, Binärfiles, Sourcecode und Dokumentation),
// + dass eine Nutzung (auch auszugsweise) nur für den privaten (nicht-kommerziellen) Gebrauch zulässig ist.
// + AUSNAHME: Ein bei www.mikrokopter.de erworbener vorbestückter MK3Mag darf als Baugruppe auch in kommerziellen Systemen verbaut werden
// + Im Zweifelsfall bitte anfragen bei: info@mikrokopter.de
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Werden Teile des Quellcodes (mit oder ohne Modifikation) weiterverwendet oder veröffentlicht,
// + Werden Teile des Quellcodes (mit oder ohne Modifikation) weiterverwendet oder veröffentlicht,
// + unterliegen sie auch diesen Nutzungsbedingungen und diese Nutzungsbedingungen incl. Copyright müssen dann beiliegen
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Sollte die Software (auch auszugesweise) oder sonstige Informationen des MikroKopter-Projekts
29,19 → 29,19
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Die Funktion printf_P() unterliegt ihrer eigenen Lizenz und ist hiervon nicht betroffen
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Redistributions of source code (with or without modifications) must retain the above copyright notice,
// + Redistributions of source code (with or without modifications) must retain the above copyright notice,
// + this list of conditions and the following disclaimer.
// + * PORTING this software (or parts of it) to systems (other than hardware from www.mikrokopter.de) is NOT allowed
// + * Neither the name of the copyright holders nor the names of contributors may be used to endorse or promote products derived
// + from this software without specific prior written permission.
// + * The use of this project (hardware, software, binary files, sources and documentation) is only permittet
// + * The use of this project (hardware, software, binary files, sources and documentation) is only permittet
// + for non-commercial use (directly or indirectly)
// + Commercial use (for excample: selling of MikroKopters, selling of PCBs, assembly, ...) is only permitted
// + Commercial use (for excample: selling of MikroKopters, selling of PCBs, assembly, ...) is only permitted
// + with our written permission
// + Exception: A preassembled MK3Mag, purchased from www.mikrokopter.de may be used as a part of commercial systems
// + In case of doubt please contact: info@MikroKopter.de
// + * If sources or documentations are redistributet on other webpages, our webpage (http://www.MikroKopter.de) must be
// + clearly linked as origin
// + * If sources or documentations are redistributet on other webpages, our webpage (http://www.MikroKopter.de) must be
// + clearly linked as origin
// + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52,167 → 52,239
// + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// + POSSIBILITY OF SUCH DAMAGE.
// + POSSIBILITY OF SUCH DAMAGE.
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/twi.h>
#include "twislave.h"
#include "uart.h"
#include "main.h"
#include "timer0.h"
#include "led.h"
 
unsigned char I2C_RxBufferSize, I2C_TxBufferSize;
unsigned char *I2C_TxBuffer, *I2C_RxBuffer;
unsigned char Tx_Idx=0, Rx_Idx=0, I2C_Direction;
unsigned char I2C_Command;
unsigned char Tx_Idx, Rx_Idx;
 
struct str_I2C_Heading I2C_Heading;
struct str_I2C_WriteNickRoll I2C_WriteNickRoll;
struct str_I2C_Mag I2C_Mag;
struct str_I2C_EEPROM I2C_ReadEEPROM, I2C_WriteEEPROM;
struct str_I2C_Version I2C_Version;
struct str_I2C_WriteCal I2C_WriteCal;
struct str_I2C_Acc I2C_Acc;
volatile uint8_t I2C_RxBufferSize = 0, I2C_TxBufferSize = 0;
volatile uint8_t *I2C_TxBuffer = 0, *I2C_RxBuffer = 0;
volatile uint8_t Tx_Idx = 0, Rx_Idx = 0;
 
volatile uint8_t I2C_PrimRxBuffer[10];
 
//############################################################################
//I2C (TWI) Interface Init
void InitIC2_Slave(void)
//############################################################################
{
TWAR = I2C_SLAVE_ADDRESS; // Eigene Adresse setzen
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWIE) | (1<<TWEA);
I2C_Version.Hauptversion = VersionInfo.Hauptversion;
I2C_Version.Nebenversion = VersionInfo.Nebenversion;
I2C_Version.Comp = 1;
uint8_t NC_Connected = 0;
I2C_Heading_t I2C_Heading;
I2C_WriteAttitude_t I2C_WriteAttitude;
I2C_Mag_t I2C_Mag;
I2C_Version_t I2C_Version;
I2C_WriteCal_t I2C_WriteCal;
 
 
void I2C_Init(void)
{
 
uint8_t sreg;
 
// backup status register
sreg = SREG;
// disable global interrupts
cli();
 
// SCK/SCL and MISO/SDA are at put together on the same connector pin in the schematic
 
// set PB4 (SCK) and PB5 (MISO) as input pull up
DDRB &= ~((1<<DDB4)|(1<<DDB5));
PORTB |= ((1<<PORTB4)|(1<<PORTB5));
 
// set PC4 (SDA) and PC5 (SCL) as input tristate
DDRC &= ~((1<<DDC4)|(1<<DDC5));
PORTC &= ~((1<<PORTC4)|(1<<PORTC5));
 
I2C_TxBuffer = 0;
Tx_Idx = 0;
I2C_TxBufferSize = 0;
I2C_RxBuffer = 0;
Rx_Idx = 0;
I2C_RxBufferSize = 0;
 
 
 
TWCR &= ~(1<<TWSTA)|(1<<TWSTO);
TWCR|= (1<<TWEA) | (1<<TWEN)|(1<<TWIE);
 
// set own address
// set own address in the upper 7 bits
TWAR = I2C_SLAVE_ADDRESS; // set own address only the upper 7 bits are relevant
// TWI Control Register
// enable TWI Acknowledge Bit (TWEA = 1)
// disable TWI START Condition Bit (TWSTA = 0), SLAVE
// disable TWI STOP Condition Bit (TWSTO = 0), SLAVE
// enable TWI (TWEN = 1)
// enable TWI Interrupt (TWIE = 1)
TWCR |= (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA)|(0<<TWSTA)|(1<<TWSTO)|(0<<TWWC);
// update version info
I2C_Version.Major = VERSION_MAJOR;
I2C_Version.Minor = VERSION_MINOR;
I2C_Version.Compatible = I2C_PROTOCOL_COMP;
 
// resore status register
SREG = sreg;
}
#define TWCR_ACK TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(0<<TWWC)
//############################################################################
//ISR, die bei einem Ereignis auf dem Bus ausgelöst wird. Im Register TWSR befindet
//sich dann ein Statuscode, anhand dessen die Situation festgestellt werden kann.
 
// send ACK after recieving a byte / ACK is expected after transmitting a byte
#define TWCR_ACK TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(0<<TWWC)
// send no ACK after recieving a byte / No ACK is expected after transmitting a byte
#define TWCR_NACK TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(0<<TWWC)
// switched to the non adressed slave mode
#define TWCR_RESET TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(0<<TWWC)
// The bit pattern for TWCR_ACK and TWCR_RESET are equal. This is no errro but used for better understanding.
#define TWCR_CLEARBUS TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA)|(0<<TWSTA)|(1<<TWSTO)|(0<<TWWC)
 
ISR (TWI_vect)
//############################################################################
{
switch (TWSR & 0xF8)
{
case SR_SLA_ACK:
//TWCR |= (1<<TWINT);
Rx_Idx = 0;
TWCR_ACK;
{
uint8_t data;
static uint8_t crc;
// check event
switch (TW_STATUS)
{
case TW_SR_SLA_ACK: // slave addressed in receiver mode and ack has been returned
Rx_Idx = 0xFF; // reset rx buffer pointer
TWCR_ACK; // trigger receiving of first data byte and send ack afterwards
return;
// Daten Empfangen
case SR_PREV_ACK:
if (Rx_Idx == 0)
{ I2C_Command = TWDR;
switch(I2C_Command)
{
case I2C_CMD_VERSION:
I2C_TxBuffer = (unsigned char *)&I2C_Version;
 
case TW_SR_DATA_ACK: // data has been received and ack has been returned
data = TWDR;
if (Rx_Idx == 0xFF)
{ // if the fisrt byte after slave addressing was received
switch(data)
{
case I2C_CMD_VERSION:
I2C_TxBuffer = (uint8_t *)&I2C_Version;
I2C_TxBufferSize = sizeof(I2C_Version);
I2C_RxBuffer = 0;
I2C_RxBufferSize = 0;
break;
case I2C_CMD_WRITE_EEPROM:
I2C_TxBufferSize = 0;
I2C_RxBuffer = (unsigned char *)&I2C_WriteEEPROM;
I2C_RxBufferSize = sizeof(I2C_WriteEEPROM);
break;
break;
 
case I2C_CMD_WRITE_CAL:
case I2C_CMD_WRITE_CAL:
I2C_TxBuffer = 0;
I2C_TxBufferSize = 0;
I2C_RxBuffer = (unsigned char *)&I2C_WriteCal;
I2C_RxBuffer = (uint8_t *)&I2C_WriteCal;
I2C_RxBufferSize = sizeof(I2C_WriteCal);
break;
break;
 
case I2C_CMD_READ_EEPROM:
I2C_TxBuffer = (unsigned char *)&I2C_ReadEEPROM.Inhalt;
I2C_TxBufferSize = 2;
I2C_RxBuffer = (unsigned char *)&I2C_ReadEEPROM;
I2C_RxBufferSize = 1;
break;
case I2C_CMD_READ_MAG:
I2C_TxBuffer = (unsigned char *)&I2C_Mag;
case I2C_CMD_READ_MAG:
I2C_TxBuffer = (uint8_t *)&I2C_Mag;
I2C_TxBufferSize = sizeof(I2C_Mag);
I2C_RxBuffer = 0;
I2C_RxBufferSize = 0;
I2C_Mag.MagX = MagnetN;
I2C_Mag.MagY = MagnetR;
I2C_Mag.MagZ = MagnetZ;
break;
case I2C_CMD_READ_ACC:
I2C_TxBuffer = (unsigned char *)&I2C_Acc;
I2C_TxBufferSize = sizeof(I2C_Acc);
I2C_RxBufferSize = 0;
I2C_Acc.AccN = RawAccN;
I2C_Acc.AccR = RawAccR;
I2C_Acc.AccZ = RawAccZ;
break;
case I2C_CMD_READ_HEADING:
I2C_TxBuffer = (unsigned char *)&I2C_Heading;
 
I2C_Mag.MagX = MagX;
I2C_Mag.MagY = MagY;
I2C_Mag.MagZ = MagZ;
break;
 
case I2C_CMD_READ_HEADING:
I2C_TxBuffer = (uint8_t *)&I2C_Heading;
I2C_TxBufferSize = sizeof(I2C_Heading);
I2C_RxBuffer = (unsigned char *)&I2C_WriteNickRoll;
I2C_RxBufferSize = sizeof(I2C_WriteNickRoll);
I2C_RxBuffer = (uint8_t *)&I2C_WriteAttitude;
I2C_RxBufferSize = sizeof(I2C_WriteAttitude);
I2C_Heading.Heading = Heading;
ExternData.Winkel[NICK] = I2C_WriteNickRoll.Nick;
ExternData.Winkel[ROLL] = I2C_WriteNickRoll.Roll;
AngleSource = 1;
break;
case I2C_CMD_READ_HEADING_INTERNAL_ACC:
I2C_TxBuffer = (unsigned char *)&I2C_Heading;
I2C_TxBufferSize = sizeof(I2C_Heading);
I2C_RxBufferSize = 0;
I2C_Heading.Heading = Heading;
ExternData.Winkel[NICK] = 0;
ExternData.Winkel[ROLL] = 0;
AngleSource = 0;
break;
AttitudeSource = ATTITUDE_SOURCE_I2C;
Orientation = ORIENTATION_NC;
NC_Connected = 255;
break;
default: // unknown command id
I2C_RxBuffer = 0;
I2C_RxBufferSize = 0;
I2C_TxBuffer = 0;
I2C_TxBufferSize = 0;
break;
}
Rx_Idx = 0; // set rx buffer index to start of the buffer
crc = data;
}
else // Rx_Idx != 0xFF
{
// fill receiver buffer with the byte that has been received
// if buffer exist and there is still some free space
if(Rx_Idx < I2C_RxBufferSize)
{
I2C_PrimRxBuffer[Rx_Idx] = data;
crc += data;
}
else if (Rx_Idx == I2C_RxBufferSize) // crc byte was transfered
{ // if checksum matched
if(crc == data)
{ // and RxBuffer exist
if(I2C_RxBuffer != 0)
{ // copy data to rx buffer
for(data = 0; data < I2C_RxBufferSize; data++)
{
I2C_RxBuffer[data] = I2C_PrimRxBuffer[data];
}
}
DebugOut.Analog[31]++;
}
else
{
DebugOut.Analog[30]++;
}
}
// else ignore data
Rx_Idx++;
}
TWCR_ACK;
return;
 
}
case TW_ST_SLA_ACK: // slave transmitter selected
// reset index to start of tx buffer
Tx_Idx = 0;
crc = 0;
// if tx buffer exist and there is at least one byte to transfer
if((I2C_TxBuffer != 0) && (I2C_TxBufferSize > 1))
{
data = I2C_TxBuffer[Tx_Idx];
 
}
else
{ // send 0x00 if no tx buffer exist or all bytes of the tx buffer have been transmitted
data = 0x00;
}
crc += data;
Tx_Idx++;
TWDR = data;
TWCR_ACK;
return;
 
case TW_ST_DATA_ACK: // data byte has been transmitted ack has been received
// put next byte from tx buffer to the data register
if((I2C_TxBuffer != 0) && (Tx_Idx < I2C_TxBufferSize))
{
if ((Rx_Idx-1) < I2C_RxBufferSize) I2C_RxBuffer[Rx_Idx-1] = TWDR;
data = I2C_TxBuffer[Tx_Idx];
crc += data;
}
Rx_Idx++;
I2C_Timeout = 500;
//TWCR |= (1<<TWINT);
else if (Tx_Idx == I2C_TxBufferSize)
{ // send crc byte at the end
data = crc;
}
else
{
data = 0x00;
}
Tx_Idx++;
TWDR = data;
TWCR_ACK;
return;
// Daten Senden
case SW_SLA_ACK:
Tx_Idx = 0;
if (I2C_TxBufferSize > 0) TWDR = I2C_TxBuffer[Tx_Idx++];
// TWCR |= (1<<TWINT) | (1<< TWEA);
TWCR_ACK;
return;
// Daten Senden
case SW_DATA_ACK:
if (Tx_Idx < I2C_TxBufferSize) TWDR = I2C_TxBuffer[Tx_Idx++];
else TWDR = 0x00;
//TWCR |= (1<<TWINT) | (1<< TWEA);
TWCR_ACK;
return;
// Bus-Fehler zurücksetzen
case TWI_BUS_ERR_2:
TWCR |=(1<<TWSTO) | (1<<TWINT);
// Bus-Fehler zurücksetzen
case TWI_BUS_ERR_1:
TWCR |=(1<<TWSTO) | (1<<TWINT);
}
TWCR =(1<<TWEA) | (1<<TWINT) | (1<<TWEN) | (1<<TWIE); // TWI Reset
 
case TW_BUS_ERROR: // Bus-Error
TWCR_CLEARBUS; // free bus, reset to nonselected slave
return;
 
case TW_ST_DATA_NACK: // data transmitted, NACK received
case TW_ST_LAST_DATA: // last data byte transmitted, ACK received
case TW_SR_STOP: // stop or repeated start condition received while selected
default:
TWCR_RESET; // switch to the not addressed slave mode, own SLA will be recognized
return;
}
}
 
 
/trunk/twislave.h
1,96 → 1,63
#ifndef _TWI_SLAVE_H_
#define _TWI_SLAVE_H_
 
#define I2C_SLAVE_ADDRESS 0x50
#include <inttypes.h>
 
#define I2C_CMD_VERSION 0x01
struct str_I2C_Version
{
unsigned char Hauptversion;
unsigned char Nebenversion;
unsigned char Comp;
} ;
#define I2C_SLAVE_ADDRESS 0x50
#define I2C_PROTOCOL_COMP 1
 
#define I2C_CMD_WRITE_EEPROM 0x0A
#define I2C_CMD_READ_EEPROM 0x0B
struct str_I2C_EEPROM
{
unsigned char Adresse;
unsigned int Inhalt;
} ;
#define I2C_CMD_VERSION 0x01
#define I2C_CMD_READ_MAG 0x02
#define I2C_CMD_READ_HEADING 0x03
#define I2C_CMD_WRITE_CAL 0x04
#define I2C_CMD_WRITE_EEPROM 0x0A
#define I2C_CMD_READ_EEPROM 0x0B
 
#define I2C_CMD_READ_MAG 0x02
struct str_I2C_Mag
 
typedef struct
{
int MagX;
int MagY;
int MagZ;
} ;
uint8_t Major;
uint8_t Minor;
uint8_t Compatible;
} I2C_Version_t;
 
#define I2C_CMD_READ_HEADING 0x03
struct str_I2C_WriteNickRoll
typedef struct
{
int Nick;
int Roll;
} ;
int16_t MagX;
int16_t MagY;
int16_t MagZ;
} I2C_Mag_t;
 
#define I2C_CMD_WRITE_CAL 0x04
struct str_I2C_WriteCal
 
typedef struct
{
unsigned char CalByte;
unsigned char Dummy1;
unsigned char Dummy2;
} ;
int16_t Nick;
int16_t Roll;
} I2C_WriteAttitude_t;
 
#define I2C_CMD_READ_HEADING_INTERNAL_ACC 0x05
 
struct str_I2C_Heading
typedef struct
{
unsigned int Heading;
} ;
uint8_t CalByte;
uint8_t Dummy1;
uint8_t Dummy2;
} I2C_WriteCal_t;
 
#define I2C_CMD_READ_ACC 0x06
struct str_I2C_Acc
typedef struct
{
int AccN;
int AccR;
int AccZ;
};
int16_t Heading;
} I2C_Heading_t;
 
extern unsigned char Tx_Idx, Rx_Idx, I2C_Direction;
extern uint8_t NC_Connected;
extern I2C_Heading_t I2C_Heading;
extern I2C_WriteAttitude_t I2C_WriteAttitude;
extern I2C_Mag_t I2C_Mag;
extern I2C_Version_t I2C_Version;
extern I2C_WriteCal_t I2C_WriteCal;
 
extern struct str_I2C_Heading I2C_Heading;
extern struct str_I2C_WriteNickRoll I2C_WriteNickRoll;
extern struct str_I2C_Mag I2C_Mag;
extern struct str_I2C_EEPROM I2C_ReadEEPROM, I2C_WriteEEPROM;
extern struct str_I2C_Version I2C_Version;
extern struct str_I2C_WriteCal I2C_WriteCal;
extern struct str_I2C_Acc I2C_Acc;
 
void I2C_Init(void);
 
extern void InitIC2_Slave (void);
 
#define TWI_BUS_ERR_1 0x00
#define TWI_BUS_ERR_2 0xF8
#endif // _TWI_SLAVE_H_
 
// Status Slave RX Mode
#define SR_SLA_ACK 0x60
#define SR_LOST_ACK 0x68
#define SR_GEN_CALL_ACK 0x70
#define GEN_LOST_ACK 0x78
#define SR_PREV_ACK 0x80
#define SR_PREV_NACK 0x88
#define GEN_PREV_ACK 0x90
#define GEN_PREV_NACK 0x98
#define STOP_CONDITION 0xA0
#define REPEATED_START 0xA0
 
// Status Slave TX mode
#define SW_SLA_ACK 0xA8
#define SW_LOST_ACK 0xB0
#define SW_DATA_ACK 0xB8
#define SW_DATA_NACK 0xC0
#define SW_LAST_ACK 0xC8
 
#endif
 
/trunk/uart.c
1,6 → 1,6
/*#######################################################################################
MK3Mag 3D-Magnet sensor
!!! THIS IS NOT FREE SOFTWARE !!!
!!! THIS IS NOT FREE SOFTWARE !!!
#######################################################################################*/
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Copyright (c) 05.2008 Holger Buss
8,15 → 8,15
// + Nur für den privaten Gebrauch
// + www.MikroKopter.com
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Die Portierung der Software (oder Teile davon) auf andere Systeme (ausser der Hardware von www.mikrokopter.de) ist nur
// + Die Portierung der Software (oder Teile davon) auf andere Systeme (ausser der Hardware von www.mikrokopter.de) ist nur
// + mit unserer Zustimmung zulässig
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Es gilt für das gesamte Projekt (Hardware, Software, Binärfiles, Sourcecode und Dokumentation),
// + dass eine Nutzung (auch auszugsweise) nur für den privaten (nicht-kommerziellen) Gebrauch zulässig ist.
// + Es gilt für das gesamte Projekt (Hardware, Software, Binärfiles, Sourcecode und Dokumentation),
// + dass eine Nutzung (auch auszugsweise) nur für den privaten (nicht-kommerziellen) Gebrauch zulässig ist.
// + AUSNAHME: Ein bei www.mikrokopter.de erworbener vorbestückter MK3Mag darf als Baugruppe auch in kommerziellen Systemen verbaut werden
// + Im Zweifelsfall bitte anfragen bei: info@mikrokopter.de
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Werden Teile des Quellcodes (mit oder ohne Modifikation) weiterverwendet oder veröffentlicht,
// + Werden Teile des Quellcodes (mit oder ohne Modifikation) weiterverwendet oder veröffentlicht,
// + unterliegen sie auch diesen Nutzungsbedingungen und diese Nutzungsbedingungen incl. Copyright müssen dann beiliegen
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Sollte die Software (auch auszugesweise) oder sonstige Informationen des MikroKopter-Projekts
29,19 → 29,19
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Die Funktion printf_P() unterliegt ihrer eigenen Lizenz und ist hiervon nicht betroffen
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Redistributions of source code (with or without modifications) must retain the above copyright notice,
// + Redistributions of source code (with or without modifications) must retain the above copyright notice,
// + this list of conditions and the following disclaimer.
// + * PORTING this software (or parts of it) to systems (other than hardware from www.mikrokopter.de) is NOT allowed
// + * Neither the name of the copyright holders nor the names of contributors may be used to endorse or promote products derived
// + from this software without specific prior written permission.
// + * The use of this project (hardware, software, binary files, sources and documentation) is only permittet
// + * The use of this project (hardware, software, binary files, sources and documentation) is only permittet
// + for non-commercial use (directly or indirectly)
// + Commercial use (for excample: selling of MikroKopters, selling of PCBs, assembly, ...) is only permitted
// + Commercial use (for excample: selling of MikroKopters, selling of PCBs, assembly, ...) is only permitted
// + with our written permission
// + Exception: A preassembled MK3Mag, purchased from www.mikrokopter.de may be used as a part of commercial systems
// + In case of doubt please contact: info@MikroKopter.de
// + * If sources or documentations are redistributet on other webpages, our webpage (http://www.MikroKopter.de) must be
// + clearly linked as origin
// + * If sources or documentations are redistributet on other webpages, our webpage (http://www.MikroKopter.de) must be
// + clearly linked as origin
// + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52,435 → 52,475
// + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// + POSSIBILITY OF SUCH DAMAGE.
// + POSSIBILITY OF SUCH DAMAGE.
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
#include "main.h"
#include "uart.h"
#include "timer0.h"
#include "twislave.h"
 
#define MAX_SENDE_BUFF 100
#define MAX_EMPFANGS_BUFF 100
 
unsigned volatile char SIO_Sollwert = 0;
unsigned volatile char SioTmp = 0;
unsigned volatile char SendeBuffer[MAX_SENDE_BUFF];
unsigned volatile char RxdBuffer[MAX_EMPFANGS_BUFF];
unsigned volatile char NeuerDatensatzEmpfangen = 0;
unsigned volatile char UebertragungAbgeschlossen = 1;
unsigned char GetVersionAnforderung = 0,DebugTextAnforderung = 0,DebugGetAnforderung = 0, KompassAntwort = 0;
unsigned char MeineSlaveAdresse;
unsigned char MotorTest[4] = {0,0,0,0};
unsigned volatile char AnzahlEmpfangsBytes = 0;
unsigned char PcZugriff;
#define FALSE 0
#define TRUE 1
 
struct str_DebugOut DebugOut;
struct str_ExternData ExternData;
struct str_ExternControl ExternControl;
struct str_VersionInfo VersionInfo;
// keep buffers as small as possible
#define TXD_BUFFER_LEN 100
#define RXD_BUFFER_LEN 30
 
volatile uint8_t txd_buffer[TXD_BUFFER_LEN];
volatile uint8_t rxd_buffer_locked = FALSE;
volatile uint8_t rxd_buffer[RXD_BUFFER_LEN];
volatile uint8_t txd_complete = TRUE;
volatile uint8_t ReceivedBytes = 0;
 
#define VERSION_INFO 0x01
#define DEBUG_DATA 0x02
#define DEBUG_LABEL 0x04
#define COMPASS_HEADING 0x08
 
int Debug_Timer;
uint8_t RequestFlags = 0x00;
uint8_t RequestDebugLabel = 0;
 
const unsigned char ANALOG_TEXT[32][16] =
uint8_t PC_Connected = 0;
uint8_t FC_Connected = 0;
 
uint8_t MySlaveAddr = 0;
 
 
DebugOut_t DebugOut;
ExternData_t ExternData;
ExternControl_t ExternControl;
VersionInfo_t VersionInfo;
 
uint16_t Debug_Timer;
 
const uint8_t ANALOG_LABEL[32][16] =
{
//1234567890123456
"Magnet N ", //0
"Magnet R ",
"Magnet X ", //0
"Magnet Y ",
"Magnet Z ",
"Raw N ",
"Raw R ",
"Raw Z ", //5
"Angle N ",
"Angle R ",
"Xmin ",
"Xmax ",
"Ymin ", //10
"Ymax ",
"Zmin ",
"ZMax ",
"Compass ",
"Calstate ", //15
"RawMagnet X ",
"RawMagnet Y ",
"RawMagnet Z ", //5
"Attitude Nick ",
"Attitude Roll ",
"Magnet X Offset ",
"Magnet X Range ",
"Magnet Y Offset ", //10
"Magnet Y Range ",
"Magnet Z Offset ",
"Magnet Z Range ",
"Calstate ",
"Heading ", //15
"User0 ",
"User1 ",
"AccN ",
"AccR ",
"AccZ ", //20
"RawAccN ",
"RawAccR ",
"RawAccZ ",
"OffsetAccN ",
"OffsetAccR ", //25
"OffsetAccZ ",
"Acc X ",
"Acc Y ",
"Acc Z ", //20
"RawAcc X ",
"RawAcc Y ",
"RawAcc Z ",
"Acc X Offset ",
"Acc Y Offset ", //25
"Acc Z Offset ",
"Analog27 ",
"Analog28 ",
"Analog29 ",
"Analog30 ", //30
"Analog31 "
"I2C Error ", //30
"I2C Okay "
};
 
 
/****************************************************************/
/* Initialization of the USART0 */
/****************************************************************/
void USART0_Init (void)
{
uint16_t ubrr = (uint16_t) ((uint32_t) F_CPU/(8 * BAUD_RATE) - 1);
 
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//++ Sende-Part der Datenübertragung
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
SIGNAL(INT_VEC_TX)
{
static unsigned int ptr = 0;
unsigned char tmp_tx;
if(!UebertragungAbgeschlossen)
{
ptr++; // die [0] wurde schon gesendet
tmp_tx = SendeBuffer[ptr];
if((tmp_tx == '\r') || (ptr == MAX_SENDE_BUFF))
{
ptr = 0;
UebertragungAbgeschlossen = 1;
}
UDR = tmp_tx;
}
else ptr = 0;
// disable all interrupts before configuration
cli();
 
// disable RX-Interrupt
UCSR0B &= ~(1 << RXCIE0);
// disable TX-Interrupt
UCSR0B &= ~(1 << TXCIE0);
 
// set direction of RXD0 and TXD0 pins
 
// set RXD0 (PD0) as an input pin tristate
DDRD &= ~(1 << DDD0);
PORTD &= ~(1 << PORTD0);
// set TXD0 (PD1) as an output pin
DDRD |= (1 << DDD1);
PORTD &= ~(1 << PORTD1);
 
 
// USART0 Baud Rate Register
// set clock divider
UBRR0H = (uint8_t)(ubrr >> 8);
UBRR0L = (uint8_t)ubrr;
 
// USART0 Control and Status Register A, B, C
 
// enable double speed operation
UCSR0A |= (1 << U2X0);
 
// set asynchronous mode
UCSR0C &= ~(1 << UMSEL01);
UCSR0C &= ~(1 << UMSEL00);
// no parity
UCSR0C &= ~(1 << UPM01);
UCSR0C &= ~(1 << UPM00);
// 1 stop bit
UCSR0C &= ~(1 << USBS0);
// 8-bit
UCSR0B &= ~(1 << UCSZ02);
UCSR0C |= (1 << UCSZ01);
UCSR0C |= (1 << UCSZ00);
 
// enable receiver and transmitter
UCSR0B |= (1 << RXEN0);
UCSR0B |= (1 << TXEN0);
 
// flush receive buffer
while ( UCSR0A & (1<<RXC0) ) UDR0;
 
// enable RX-Interrupt
UCSR0B |= (1 << RXCIE0);
// enable TX-Interrupt
UCSR0B |= (1 << TXCIE0);
 
rxd_buffer_locked = FALSE;
txd_complete = TRUE;
 
 
VersionInfo.Major = VERSION_MAJOR;
VersionInfo.Minor = VERSION_MINOR;
VersionInfo.PCCompatible = VERSION_COMPATIBLE;
 
 
// Version beim Start ausgeben (nicht schön, aber geht... )
USART0_putchar ('\n');
USART0_putchar ('C');
USART0_putchar ('P');
USART0_putchar (':');
USART0_putchar ('V');
USART0_putchar (0x30 + VERSION_MAJOR);
USART0_putchar ('.');
USART0_putchar (0x30 + VERSION_MINOR/10);
USART0_putchar (0x30 + VERSION_MINOR%10);
USART0_putchar ('\n');
}
 
void SendUart(void)
// ---------------------------------------------------------------------------------
void USART0_EnableTXD(void)
{
static unsigned int ptr = 0;
unsigned char tmp_tx;
if(!(USR & 0x40)) return;
if(!UebertragungAbgeschlossen)
{
ptr++; // die [0] wurde schon gesendet
tmp_tx = SendeBuffer[ptr];
if((tmp_tx == '\r') || (ptr == MAX_SENDE_BUFF))
{
ptr = 0;
UebertragungAbgeschlossen = 1;
}
USR |= (1<TXC0);
UDR = tmp_tx;
}
else ptr = 0;
DDRD |= (1<<DDD1); // set TXD pin as output
PORTD &= ~(1 << PORTD1);
UCSR0B |= (1 << TXEN0); // enable TX in USART
UCSR0B |= (1 << TXCIE0); // disable TX-Interrupt
}
 
// --------------------------------------------------------------------------
void Decode64(unsigned char *ptrOut, unsigned char len, unsigned char ptrIn,unsigned char max) // Wohin mit den Daten; Wie lang; Wo im RxdBuffer
// ---------------------------------------------------------------------------------
void USART0_DisableTXD(void)
{
unsigned char a,b,c,d;
unsigned char ptr = 0;
unsigned char x,y,z;
while(len)
{
a = RxdBuffer[ptrIn++] - '=';
b = RxdBuffer[ptrIn++] - '=';
c = RxdBuffer[ptrIn++] - '=';
d = RxdBuffer[ptrIn++] - '=';
if(ptrIn > max - 2) break; // nicht mehr Daten verarbeiten, als empfangen wurden
while(!txd_complete){ };
 
x = (a << 2) | (b >> 4);
y = ((b & 0x0f) << 4) | (c >> 2);
z = ((c & 0x03) << 6) | d;
UCSR0B &= ~(1 << TXCIE0); // disable TX-Interrupt
UCSR0B &= ~(1 << TXEN0); // disable TXD in USART
DDRD &= ~(1<<DDD1); // set TXD pin as input
PORTD &= ~(1 << PORTD1);
}
 
if(len--) ptrOut[ptr++] = x; else break;
if(len--) ptrOut[ptr++] = y; else break;
if(len--) ptrOut[ptr++] = z; else break;
}
 
/****************************************************************/
/* USART0 transmitter ISR */
/****************************************************************/
ISR(USART_TX_vect)
{
static uint16_t ptr_txd_buffer = 0;
uint8_t tmp_tx;
if(!txd_complete) // transmission not completed
{
ptr_txd_buffer++; // die [0] wurde schon gesendet
tmp_tx = txd_buffer[ptr_txd_buffer];
// if terminating character or end of txd buffer was reached
if((tmp_tx == '\r') || (ptr_txd_buffer == TXD_BUFFER_LEN))
{
ptr_txd_buffer = 0; // reset txd pointer
txd_complete = TRUE; // stop transmission
}
UDR0 = tmp_tx; // send current byte will trigger this ISR again
}
// transmission completed
else ptr_txd_buffer = 0;
}
 
 
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//++ Empfangs-Part der Datenübertragung
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
SIGNAL(INT_VEC_RX)
/****************************************************************/
/* USART0 receiver ISR */
/****************************************************************/
ISR(USART_RX_vect)
{
static unsigned int crc;
static unsigned char crc1,crc2,buf_ptr;
static unsigned char UartState = 0;
unsigned char CrcOkay = 0;
SioTmp = UDR;
if(buf_ptr >= MAX_EMPFANGS_BUFF) UartState = 0;
if(SioTmp == '\r' && UartState == 2)
{
UartState = 0;
crc -= RxdBuffer[buf_ptr-2];
crc -= RxdBuffer[buf_ptr-1];
crc %= 4096;
crc1 = '=' + crc / 64;
crc2 = '=' + crc % 64;
CrcOkay = 0;
if((crc1 == RxdBuffer[buf_ptr-2]) && (crc2 == RxdBuffer[buf_ptr-1])) CrcOkay = 1; else { CrcOkay = 0; };
if(CrcOkay) // Datensatz schon verarbeitet
{
NeuerDatensatzEmpfangen = 1;
AnzahlEmpfangsBytes = buf_ptr;
RxdBuffer[buf_ptr] = '\r';
if((RxdBuffer[2] == 'R')) wdt_enable(WDTO_250MS); // Reset-Commando
// uart_putchar(RxdBuffer[2]);
}
}
else
switch(UartState)
{
case 0:
if(SioTmp == '#' && !NeuerDatensatzEmpfangen) UartState = 1; // Startzeichen und Daten schon verarbeitet
buf_ptr = 0;
RxdBuffer[buf_ptr++] = SioTmp;
crc = SioTmp;
break;
case 1: // Adresse auswerten
UartState++;
RxdBuffer[buf_ptr++] = SioTmp;
crc += SioTmp;
break;
case 2: // Eingangsdaten sammeln
RxdBuffer[buf_ptr] = SioTmp;
if(buf_ptr < MAX_EMPFANGS_BUFF) buf_ptr++;
else UartState = 0;
crc += SioTmp;
break;
default:
UartState = 0;
break;
}
static uint16_t crc;
uint8_t crc1, crc2;
uint8_t c;
static uint8_t ptr_rxd_buffer = 0;
 
};
c = UDR0; // catch the received byte
 
if(rxd_buffer_locked) return; // if rxd buffer is locked immediately return
 
// --------------------------------------------------------------------------
void AddCRC(unsigned int wieviele)
{
unsigned int tmpCRC = 0,i;
for(i = 0; i < wieviele;i++)
{
tmpCRC += SendeBuffer[i];
}
tmpCRC %= 4096;
SendeBuffer[i++] = '=' + tmpCRC / 64;
SendeBuffer[i++] = '=' + tmpCRC % 64;
SendeBuffer[i++] = '\r';
UebertragungAbgeschlossen = 0;
UDR = SendeBuffer[0];
// the rxd buffer is unlocked
if((ptr_rxd_buffer == 0) && (c == '#')) // if rxd buffer is empty and syncronisation character is received
{
rxd_buffer[ptr_rxd_buffer++] = c; // copy 1st byte to buffer
crc = c; // init crc
}
#if 0
else if (ptr_rxd_buffer == 1) // handle address
{
rxd_buffer[ptr_rxd_buffer++] = c; // copy byte to rxd buffer
crc += c; // update crc
}
#endif
else if (ptr_rxd_buffer < RXD_BUFFER_LEN) // collect incomming bytes
{
if(c != '\r') // no termination character
{
rxd_buffer[ptr_rxd_buffer++] = c; // copy byte to rxd buffer
crc += c; // update crc
}
else // termination character was received
{
// the last 2 bytes are no subject for checksum calculation
// they are the checksum itself
crc -= rxd_buffer[ptr_rxd_buffer-2];
crc -= rxd_buffer[ptr_rxd_buffer-1];
// calculate checksum from transmitted data
crc %= 4096;
crc1 = '=' + crc / 64;
crc2 = '=' + crc % 64;
// compare checksum to transmitted checksum bytes
if((crc1 == rxd_buffer[ptr_rxd_buffer-2]) && (crc2 == rxd_buffer[ptr_rxd_buffer-1]))
{ // checksum valid
rxd_buffer_locked = TRUE; // lock the rxd buffer
ReceivedBytes = ptr_rxd_buffer; // store number of received bytes
rxd_buffer[ptr_rxd_buffer] = '\r'; // set termination character
// if 2nd byte is an 'R' enable watchdog that will result in an reset
if(rxd_buffer[2] == 'R') {wdt_enable(WDTO_250MS);} // Reset-Commando
}
else
{ // checksum invalid
rxd_buffer_locked = FALSE; // unlock rxd buffer
}
ptr_rxd_buffer = 0; // reset rxd buffer pointer
}
}
else // rxd buffer overrun
{
ptr_rxd_buffer = 0; // reset rxd buffer
rxd_buffer_locked = FALSE; // unlock rxd buffer
}
}
 
 
// --------------------------------------------------------------------------
void SendOutData(unsigned char cmd,unsigned char modul, unsigned char *snd, unsigned char len)
void AddCRC(uint16_t datalen)
{
unsigned int pt = 0;
unsigned char a,b,c;
unsigned char ptr = 0;
SendeBuffer[pt++] = '#'; // Startzeichen
SendeBuffer[pt++] = modul; // Adresse (a=0; b=1,...)
SendeBuffer[pt++] = cmd; // Commando
 
while(len)
{
if(len) { a = snd[ptr++]; len--;} else a = 0;
if(len) { b = snd[ptr++]; len--;} else b = 0;
if(len) { c = snd[ptr++]; len--;} else c = 0;
SendeBuffer[pt++] = '=' + (a >> 2);
SendeBuffer[pt++] = '=' + (((a & 0x03) << 4) | ((b & 0xf0) >> 4));
SendeBuffer[pt++] = '=' + (((b & 0x0f) << 2) | ((c & 0xc0) >> 6));
SendeBuffer[pt++] = '=' + ( c & 0x3f);
}
AddCRC(pt);
uint16_t tmpCRC = 0, i;
for(i = 0; i < datalen; i++)
{
tmpCRC += txd_buffer[i];
}
tmpCRC %= 4096;
txd_buffer[i++] = '=' + tmpCRC / 64;
txd_buffer[i++] = '=' + tmpCRC % 64;
txd_buffer[i++] = '\r';
txd_complete = FALSE;
UDR0 = txd_buffer[0]; // initiates the transmission (continued in the TXD ISR)
}
 
 
 
//############################################################################
//Routine für die Serielle Ausgabe
int uart_putchar (char c)
//############################################################################
// --------------------------------------------------------------------------
void SendOutData(uint8_t cmd,uint8_t module, uint8_t *snd, uint8_t len)
{
if(!(UCR & (1 << TXEN))) return (0);
if (c == '\n')
uart_putchar('\r');
//Warten solange bis Zeichen gesendet wurde
loop_until_bit_is_set(USR, UDRE);
//Ausgabe des Zeichens
UDR = c;
return (0);
uint16_t pt = 0;
uint8_t a,b,c;
uint8_t ptr = 0;
 
txd_buffer[pt++] = '#'; // Start character
txd_buffer[pt++] = module; // Address (a=0; b=1,...)
txd_buffer[pt++] = cmd; // Command
 
while(len)
{
if(len) { a = snd[ptr++]; len--;} else a = 0;
if(len) { b = snd[ptr++]; len--;} else b = 0;
if(len) { c = snd[ptr++]; len--;} else c = 0;
txd_buffer[pt++] = '=' + (a >> 2);
txd_buffer[pt++] = '=' + (((a & 0x03) << 4) | ((b & 0xf0) >> 4));
txd_buffer[pt++] = '=' + (((b & 0x0f) << 2) | ((c & 0xc0) >> 6));
txd_buffer[pt++] = '=' + ( c & 0x3f);
}
AddCRC(pt); // add checksum after data block and initates the transmission
}
 
 
// --------------------------------------------------------------------------
void WriteProgramData(unsigned int pos, unsigned char wert)
void Decode64(uint8_t *ptrOut, uint8_t len, uint8_t ptrIn, uint8_t max)
{
}
uint8_t a,b,c,d;
uint8_t ptr = 0;
uint8_t x,y,z;
while(len)
{
a = rxd_buffer[ptrIn++] - '=';
b = rxd_buffer[ptrIn++] - '=';
c = rxd_buffer[ptrIn++] - '=';
d = rxd_buffer[ptrIn++] - '=';
if(ptrIn > max - 2) break;
 
void UART_InterruptEnable(void)
{
UCSRB |= (1<<RXCIE); // serieller Empfangsinterrupt
// TX-Interrupt Freigabe
UCSRB |= (1<<TXCIE);
x = (a << 2) | (b >> 4);
y = ((b & 0x0f) << 4) | (c >> 2);
z = ((c & 0x03) << 6) | d;
 
if(len--) ptrOut[ptr++] = x; else break;
if(len--) ptrOut[ptr++] = y; else break;
if(len--) ptrOut[ptr++] = z; else break;
}
}
 
//############################################################################
//INstallation der Seriellen Schnittstelle
void UART_Init (void)
//############################################################################
 
// --------------------------------------------------------------------------
int16_t USART0_putchar (int8_t c)
{
//Enable TXEN im Register UCR TX-Data Enable & RX Enable
 
UCR=(1 << TXEN) | (1 << RXEN);
// UART Double Speed (U2X)
USR |= (1<<U2X);
 
//Teiler wird gesetzt
UBRR= (SYSCLK / (BAUD_RATE * 8L) -1 );
//öffnet einen Kanal für printf (STDOUT)
// fdevopen (uart_putchar, NULL);
Debug_Timer = SetDelay(200);
// Version beim Start ausgeben (nicht schön, aber geht... )
uart_putchar ('\n');uart_putchar ('C');uart_putchar ('P');uart_putchar (':');
uart_putchar ('V');uart_putchar (0x30 + VERSION_HAUPTVERSION);uart_putchar ('.');uart_putchar (0x30 + VERSION_NEBENVERSION/10); uart_putchar (0x30 + VERSION_NEBENVERSION%10);
uart_putchar ('\n');
// if tx is not enabled return immediatly
if(!(UCSR0B & (1 << TXEN0))) return (0);
if (c == '\n') USART0_putchar('\r');
// wait until previous character was send
loop_until_bit_is_set(UCSR0A, UDRE0);
// send character
UDR0 = c;
return (0);
}
 
 
void BearbeiteRxDaten(void)
// --------------------------------------------------------------------------
void USART0_ProcessRxData(void)
{
if(!NeuerDatensatzEmpfangen) return;
// unsigned int tmp_int_arr1[1];
// unsigned int tmp_int_arr2[2];
// unsigned int tmp_int_arr3[3];
unsigned char tmp_char_arr2[2];
// unsigned char tmp_char_arr3[3];
// unsigned char tmp_char_arr4[4];
//if(!MotorenEin)
PcZugriff = 255;
// if data in the rxd buffer are not locked immediately return
if(!rxd_buffer_locked) return;
 
switch(RxdBuffer[2])
{
case 'w':// Lagewinkel
Decode64((unsigned char *) &ExternData,sizeof(ExternData),3,AnzahlEmpfangsBytes);
DebugOut.Analog[15]++;
KompassAntwort = 1;
AngleSource = 2;
break;
case 'c':
case 'b':
Decode64((unsigned char *) &ExternControl,sizeof(ExternControl),3,AnzahlEmpfangsBytes);
// ExternData.Winkel[0] = ExternControl.Par1;
// ExternData.Winkel[1] = ExternControl.Par2;
break;
case 'v': // Version-Anforderung und Ausbaustufe
GetVersionAnforderung = 1;
PC_Connected = 255;
break;
uint8_t tmp_char_arr2[2]; // local char buffer
 
case 'a':// Texte der Analogwerte
Decode64((unsigned char *) &tmp_char_arr2[0],sizeof(tmp_char_arr2),3,AnzahlEmpfangsBytes);
DebugTextAnforderung = tmp_char_arr2[0];
PC_Connected = 255;
switch(rxd_buffer[2])
{
case 'w':// Attitude
Decode64((uint8_t *) &ExternData, sizeof(ExternData), 3, ReceivedBytes);
RequestFlags |= COMPASS_HEADING;
AttitudeSource = ATTITUDE_SOURCE_UART;
Orientation = ExternData.Orientation;
FC_Connected = 255;
break;
case 'g':// "Get"-Anforderung für Debug-Daten
// Bei Get werden die vom PC einstellbaren Werte vom PC zurückgelesen
 
case 'b': // extern control
case 'c': // extern control with debug request
Decode64((uint8_t *) &ExternControl,sizeof(ExternControl), 3,ReceivedBytes);
#define KEY1 0x01
#define KEY2 0x02
#define KEY3 0x04
#define KEY4 0x08
#define KEY5 0x10
// use right arrow at display for switching the calstate
if(ExternControl.RemoteButtons & KEY2)
{
ExternData.CalState++;
if(ExternData.CalState == 6) ExternData.CalState = 0;
}
//ExternData.Attitude[0] = ExternControl.Par1;
//ExternData.Attitude[1] = ExternControl.Par2;
PC_Connected = 255;
DebugGetAnforderung = 1;
break;
case 'h':// x-1 Displayzeilen
PC_Connected = 255;
break;
/*
case 'b':
Decode64((unsigned char *) &ExternControl,sizeof(ExternControl),3,AnzahlEmpfangsBytes);
RemoteTasten |= ExternControl.RemoteTasten;
ConfirmFrame = ExternControl.Frame;
break;
case 'c':
Decode64((unsigned char *) &ExternControl,sizeof(ExternControl),3,AnzahlEmpfangsBytes);
RemoteTasten |= ExternControl.RemoteTasten;
ConfirmFrame = ExternControl.Frame;
DebugDataAnforderung = 1;
break;
case 'h':// x-1 Displayzeilen
Decode64((unsigned char *) &tmp_char_arr2[0],sizeof(tmp_char_arr2),3,AnzahlEmpfangsBytes);
RemoteTasten |= tmp_char_arr2[0];
if(tmp_char_arr2[1] == 255) NurKanalAnforderung = 1; else NurKanalAnforderung = 0; // keine Displaydaten
DebugDisplayAnforderung = 1;
break;
case 't':// Motortest
Decode64((unsigned char *) &MotorTest[0],sizeof(MotorTest),3,AnzahlEmpfangsBytes);
 
case 'h':// x-1 display columns
PC_Connected = 255;
break;
case 'k':// Keys von DubWise
Decode64((unsigned char *) &DubWiseKeys[0],sizeof(DubWiseKeys),3,AnzahlEmpfangsBytes);
ConfirmFrame = DubWiseKeys[3];
 
case 'v': // get version and board release
RequestFlags |= VERSION_INFO;
PC_Connected = 255;
break;
case 'q':// "Get"-Anforderung für Settings
// Bei Get werden die vom PC einstellbaren Werte vom PC zurückgelesen
Decode64((unsigned char *) &tmp_char_arr2[0],sizeof(tmp_char_arr2),3,AnzahlEmpfangsBytes);
if(tmp_char_arr2[0] != 0xff)
{
if(tmp_char_arr2[0] > 5) tmp_char_arr2[0] = 5;
ReadParameterSet(tmp_char_arr2[0], (unsigned char *) &EE_Parameter.Kanalbelegung[0], STRUCT_PARAM_LAENGE);
SendOutData('L' + tmp_char_arr2[0] -1,MeineSlaveAdresse,(unsigned char *) &EE_Parameter.Kanalbelegung[0],STRUCT_PARAM_LAENGE);
}
else
SendOutData('L' + GetActiveParamSetNumber()-1,MeineSlaveAdresse,(unsigned char *) &EE_Parameter.Kanalbelegung[0],STRUCT_PARAM_LAENGE);
break;
case 'l':
case 'm':
case 'n':
case 'o':
case 'p': // Parametersatz speichern
Decode64((unsigned char *) &EE_Parameter.Kanalbelegung[0],STRUCT_PARAM_LAENGE,3,AnzahlEmpfangsBytes);
WriteParameterSet(RxdBuffer[2] - 'l' + 1, (unsigned char *) &EE_Parameter.Kanalbelegung[0], STRUCT_PARAM_LAENGE);
eeprom_write_byte(&EEPromArray[EEPROM_ADR_ACTIVE_SET], RxdBuffer[2] - 'l' + 1); // aktiven Datensatz merken
Umschlag180Nick = (long) EE_Parameter.WinkelUmschlagNick * 2500L;
Umschlag180Roll = (long) EE_Parameter.WinkelUmschlagRoll * 2500L;
Piep(GetActiveParamSetNumber());
break;
*/
}
// DebugOut.AnzahlZyklen = Debug_Timer_Intervall;
NeuerDatensatzEmpfangen = 0;
 
case 'a':// Labels of the Analog Debug outputs
Decode64((uint8_t *) &tmp_char_arr2[0], sizeof(tmp_char_arr2), 3, ReceivedBytes);
RequestDebugLabel = tmp_char_arr2[0];
RequestFlags |= DEBUG_LABEL;
PC_Connected = 255;
break;
 
case 'g':// get debug data
RequestFlags |= DEBUG_DATA;
PC_Connected = 255;
break;
}
// unlock the rxd buffer after processing
rxd_buffer_locked = FALSE;
}
 
 
 
//---------------------------------------------------------------------------------------------
void DatenUebertragung(void)
void USART0_TransmitTxData(void)
{
if((CheckDelay(Debug_Timer) && UebertragungAbgeschlossen)) // im Singlestep-Betrieb in jedem Schtitt senden
{
SetDebugValues();
SendOutData('D',MeineSlaveAdresse,(unsigned char *) &DebugOut,sizeof(DebugOut));
Debug_Timer = SetDelay(250); // Sendeintervall
}
if(GetVersionAnforderung && UebertragungAbgeschlossen)
{
SendOutData('V',MeineSlaveAdresse,(unsigned char *) &VersionInfo,sizeof(VersionInfo));
GetVersionAnforderung = 0;
}
if(DebugTextAnforderung != 255) // Texte für die Analogdaten
{
SendOutData('A',DebugTextAnforderung + '0',(unsigned char *) ANALOG_TEXT[DebugTextAnforderung],16);
DebugTextAnforderung = 255;
}
if(DebugGetAnforderung && UebertragungAbgeschlossen) // Bei Get werden die vom PC einstellbaren Werte vom PC zurückgelesen
{
SendOutData('G',MeineSlaveAdresse,(unsigned char *) &ExternControl,sizeof(ExternControl));
DebugGetAnforderung = 0;
}
if(KompassAntwort && UebertragungAbgeschlossen) // Bei Get werden die vom PC einstellbaren Werte vom PC zurückgelesen
{
SendOutData('K',MeineSlaveAdresse,(unsigned char *) &I2C_Heading,sizeof(I2C_Heading));
KompassAntwort = 0;
}
if(!(UCSR0B & (1 << TXEN0))) return;
 
if(!txd_complete) return;
 
if(CheckDelay(Debug_Timer))
{
SetDebugValues();
SendOutData('D',MySlaveAddr,(uint8_t *) &DebugOut,sizeof(DebugOut));
Debug_Timer = SetDelay(250);
}
 
if(RequestFlags & DEBUG_LABEL)
{
SendOutData('A',RequestDebugLabel + '0',(uint8_t *) ANALOG_LABEL[RequestDebugLabel],16);
RequestDebugLabel = 255;
RequestFlags &= ~DEBUG_LABEL;
}
 
if(RequestFlags & VERSION_INFO)
{
SendOutData('V',MySlaveAddr,(uint8_t *) &VersionInfo, sizeof(VersionInfo));
RequestFlags &= ~VERSION_INFO;
}
 
if(RequestFlags & DEBUG_DATA)
{
SetDebugValues();
SendOutData('G',MySlaveAddr,(uint8_t *) &ExternControl,sizeof(ExternControl));
RequestFlags &= ~DEBUG_DATA;
}
 
if(RequestFlags & COMPASS_HEADING)
{
SendOutData('K',MySlaveAddr,(uint8_t *) &I2C_Heading, sizeof(I2C_Heading));
RequestFlags &= ~COMPASS_HEADING;
}
}
 
void UartPrint(unsigned char *this_text)
 
void USART0_Print(int8_t *msg)
{
unsigned char i = 0;
while(this_text[i] != 0)
{
uart_putchar(this_text[i++]);
}
uint8_t i = 0;
while(msg[i] != 0)
{
USART0_putchar(msg[i++]);
}
}
 
/trunk/uart.h
1,138 → 1,77
#ifndef _UART_H
#define _UART_H
#ifndef _UART_H_
#define _UART_H_
 
extern unsigned volatile char SIO_Sollwert;
extern unsigned volatile char UebertragungAbgeschlossen;
extern unsigned volatile char PC_DebugTimeout;
extern unsigned char MeineSlaveAdresse;
extern int Debug_Timer;
extern void UART_Init (void);
extern int uart_putchar (char c);
extern void boot_program_page (uint32_t page, uint8_t *buf);
extern void SendUart(void);
#include <inttypes.h>
 
void DatenUebertragung(void);
void BearbeiteRxDaten(void);
void UartPrint(unsigned char *this_text);
void UART_InterruptEnable(void);
 
struct str_DebugOut
{
unsigned char Digital[2];
unsigned int Analog[32]; // Debugwerte
};
 
struct str_ExternData
{
signed int Winkel[2]; // in 0,1 degree
unsigned char UserParameter[2];
unsigned char CalState;
unsigned char Orientation;
};
extern struct str_ExternData ExternData;
#define NICK 0
#define ROLL 1
 
 
struct str_ExternControl
{
unsigned char Digital[2];
unsigned char RemoteTasten;
signed char Nick;
signed char Roll;
signed char Gier;
unsigned char Gas;
signed char Hight;
unsigned char Par1;
unsigned char Par2;
unsigned char Par3;
};
extern struct str_ExternControl ExternControl;
#define BAUD_RATE 57600
 
struct str_VersionInfo
 
extern uint16_t Debug_Timer;
 
 
void USART0_Init (void);
void USART0_EnableTXD(void);
void USART0_DisableTXD(void);
void USART0_TransmitTxData(void);
void USART0_ProcessRxData(void);
int16_t USART0_putchar(int8_t c);
void USART0_Print(int8_t *msg);
 
 
 
typedef struct
{
unsigned char Hauptversion;
unsigned char Nebenversion;
unsigned char PCKompatibel;
unsigned char Rserved[7];
};
extern struct str_VersionInfo VersionInfo;
uint8_t Digital[2];
uint16_t Analog[32]; // Debugvalues
} DebugOut_t;
 
extern DebugOut_t DebugOut;
 
extern struct str_DebugOut DebugOut;
extern struct str_DebugOut DebugOut;
//Die Baud_Rate der Seriellen Schnittstelle
//#define BAUD_RATE 9600 //Baud Rate für die Serielle Schnittstelle
//#define BAUD_RATE 14400 //Baud Rate für die Serielle Schnittstelle
//#define BAUD_RATE 28800 //Baud Rate für die Serielle Schnittstelle
 
#if X3D_SIO == 1
#define BAUD_RATE 38400 //Baud Rate für die Serielle Schnittstelle
#else
#define BAUD_RATE 57600 //Baud Rate für die Serielle Schnittstelle
#endif
 
//Anpassen der seriellen Schnittstellen Register wenn ein ATMega128 benutzt wird
#if defined (__AVR_ATmega128__)
# define USR UCSR0A
# define UCR UCSR0B
# define UDR UDR0
# define UBRR UBRR0L
# define EICR EICRB
#endif
typedef struct
{
int16_t Attitude[2]; // nick and roll angle in 0.1 deg
uint8_t UserParam[2];
uint8_t CalState;
uint8_t Orientation;
} ExternData_t;
 
#if defined (__AVR_ATmega8__)
# define USR UCSRA
# define UCR UCSRB
# define UBRR UBRRL
# define EICR EICRB
# define INT_VEC_RX SIG_UART_RECV
# define INT_VEC_TX SIG_UART_TRANS
#endif
extern ExternData_t ExternData;
 
#if defined (__AVR_ATmega168__)
# define USR UCSR0A
# define UCR UCSR0B
# define UDR UDR0
# define UBRR UBRR0L
# define EICR EICR0B
# define TXEN TXEN0
# define RXEN RXEN0
# define RXCIE RXCIE0
# define TXCIE TXCIE0
# define U2X U2X0
# define UCSRB UCSR0B
# define UDRE UDRE0
# define INT_VEC_RX SIG_USART_RECV
# define INT_VEC_TX SIG_USART_TRANS
#endif
 
typedef struct
{
uint8_t Digital[2];
uint8_t RemoteButtons;
int8_t Nick;
int8_t Roll;
int8_t Yaw;
uint8_t Gas;
int8_t Height;
uint8_t Par1;
uint8_t Par2;
uint8_t Par3;
} ExternControl_t;
 
#if defined (__AVR_ATmega32__)
# define USR UCSRA
# define UCR UCSRB
# define UBRR UBRRL
# define EICR EICRB
# define INT_VEC_RX SIG_UART_RECV
# define INT_VEC_TX SIG_UART_TRANS
#endif
extern ExternControl_t ExternControl;
 
#if defined (__AVR_ATmega644__)
# define USR UCSR0A
# define UCR UCSR0B
# define UDR UDR0
# define UBRR UBRR0L
# define EICR EICR0B
# define TXEN TXEN0
# define RXEN RXEN0
# define RXCIE RXCIE0
# define TXCIE TXCIE0
# define U2X U2X0
# define UCSRB UCSR0B
# define UDRE UDRE0
# define INT_VEC_RX SIG_USART_RECV
# define INT_VEC_TX SIG_USART_TRANS
#endif
 
typedef struct
{
uint8_t Major;
uint8_t Minor;
uint8_t PCCompatible;
uint8_t Reserved[7];
} VersionInfo_t;
 
#endif //_UART_H
extern VersionInfo_t VersionInfo;
 
extern uint8_t PC_Connected;
extern uint8_t FC_Connected;
 
#endif //_UART_H_