Subversion Repositories MK3Mag

Compare Revisions

Ignore whitespace Rev 74 → Rev 75

/tags/V0.23a/uart.c
New file
0,0 → 1,682
/*#######################################################################################
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 / NON-COMMERCIAL USE ONLY
// + www.MikroKopter.com
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Die Portierung oder Nutzung 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 Portierung oder Nutzung der Software (oder Teile davon) auf andere Systeme (ausser der Hardware von www.mikrokopter.de) ist nur
// + mit unserer Zustimmung zulässig
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + 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 the sources to other systems or using the software on other systems (except 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 <avr/io.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
#include <avr/pgmspace.h>
#include <stdarg.h>
#include <string.h>
#include "main.h"
#include "menu.h"
#include "uart.h"
#include "timer0.h"
#include "twislave.h"
 
// slave addresses
#define FC_ADDRESS 1
#define NC_ADDRESS 2
#define MK3MAG_ADDRESS 3
 
#define FALSE 0
#define TRUE 1
 
// keep buffers as small as possible
#define TXD_BUFFER_LEN 120
#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;
volatile uint8_t *pRxData = 0;
volatile uint8_t RxDataLen = 0;
 
// send flags
#define RQST_VERSION_INFO 0x01
#define RQST_DEBUG_DATA 0x02
#define RQST_DEBUG_LABEL 0x04
#define RQST_COMPASS_HEADING 0x08
#define RQST_EXTERN_CTRL 0x10
#define RQST_DISPLAY_DATA 0x20
 
uint8_t RequestFlags = 0x00;
uint8_t RequestDebugLabel = 0;
uint8_t ConfirmFrame = 0;
uint8_t RemoteKeys = 0;
uint8_t DisplayLine = 0;
 
uint16_t PC_Connected = 0;
uint16_t FC_Connected = 0;
 
DebugOut_t DebugOut;
ExternData_t ExternData;
ExternControl_t ExternControl;
UART_VersionInfo_t UART_VersionInfo;
 
uint16_t DebugData_Timer;
uint16_t DebugData_Interval = 5000;
uint16_t Display_Timer;
uint16_t Display_Interval = 0;
uint16_t PotiIntervall = 50;
uint16_t PotiTimer;
 
const prog_uint8_t ANALOG_LABEL[32][16] =
{
//1234567890123456
"Magnet X ", //0
"Magnet Y ",
"Magnet Z ",
"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
" ",
" ",
"Acc X ",
"Acc Y ",
"Acc Z ", //20
"RawAcc X ",
"RawAcc Y ",
"RawAcc Z ",
"Serial Poti1 ",
"Serial Poti2 ", //25
"Serial Poti3 ",
"Heading X ",
"Heading Y ",
"Attitude Source ",
"I2C Error ", //30
"I2C Okay "
};
 
/****************************************************************/
/* Initialization of the USART0 */
/****************************************************************/
void USART0_Init (void)
{
uint8_t sreg = SREG;
uint16_t ubrr = (uint16_t) ((uint32_t) F_CPU/(8 * BAUD_RATE) - 1);
 
// 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);
 
// initialize the debug timer
DebugData_Timer = SetDelay(DebugData_Interval);
PotiTimer = SetDelay(PotiIntervall);
 
// unlock rxd_buffer
rxd_buffer_locked = FALSE;
pRxData = 0;
RxDataLen = 0;
 
// no bytes to send
txd_complete = TRUE;
 
 
UART_VersionInfo.SWMajor = VERSION_MAJOR;
UART_VersionInfo.SWMinor = VERSION_MINOR;
UART_VersionInfo.SWPatch = VERSION_PATCH;
UART_VersionInfo.ProtoMajor = VERSION_SERIAL_MAJOR;
UART_VersionInfo.ProtoMinor = VERSION_SERIAL_MINOR;
 
// send version info at startup
USART0_Putchar ('\r');
USART0_Putchar ('\n');
USART0_Putchar ('C');
USART0_Putchar ('P');
USART0_Putchar (':');
USART0_Putchar ('V');
USART0_Putchar ('0' + VERSION_MAJOR);
USART0_Putchar ('.');
USART0_Putchar ('0' + VERSION_MINOR/10);
USART0_Putchar ('0' + VERSION_MINOR%10);
USART0_Putchar ('a' + VERSION_PATCH);
USART0_Putchar ('\n');
 
// restore global interrupt flags
SREG = sreg;
}
 
// ---------------------------------------------------------------------------------
void USART0_EnableTXD(void)
{
DDRD |= (1<<DDD1); // set TXD pin as output
PORTD &= ~(1 << PORTD1);
UCSR0B |= (1 << TXEN0); // enable TX in USART
//changing the interrupt flag yields to strange effects
//UCSR0B |= (1 << TXCIE0); // enable TX-Interrupt
}
 
// ---------------------------------------------------------------------------------
void USART0_DisableTXD(void)
{
while(!txd_complete){ };
//changing the interrupt flag yields to strange effects
//UCSR0B &= ~(1 << TXCIE0); // disable TX-Interrupt
UCSR0B &= ~(1 << TXEN0); // disable TX in USART
DDRD &= ~(1<<DDD1); // set TXD pin as input
PORTD &= ~(1 << PORTD1);
}
 
/****************************************************************/
/* 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;
}
 
/****************************************************************/
/* USART0 receiver ISR */
/****************************************************************/
ISR(USART_RX_vect)
{
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
 
// 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[ptr_rxd_buffer] = '\r'; // set termination character
ReceivedBytes = ptr_rxd_buffer + 1;// store number of received bytes
rxd_buffer_locked = TRUE; // lock the rxd buffer
// 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 AddCRC(uint16_t datalen)
{
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)
}
 
 
 
// --------------------------------------------------------------------------
void SendOutData(uint8_t cmd, uint8_t address, uint8_t numofbuffers, ...) // uint8_t *pdata, uint8_t len, ...
{
va_list ap;
uint16_t pt = 0;
uint8_t a,b,c;
uint8_t ptr = 0;
 
uint8_t *pdata = 0;
int len = 0;
 
txd_buffer[pt++] = '#'; // Start character
txd_buffer[pt++] = 'a' + address; // Address (a=0; b=1,...)
txd_buffer[pt++] = cmd; // Command
 
va_start(ap, numofbuffers);
if(numofbuffers)
{
pdata = va_arg(ap, uint8_t*);
len = va_arg(ap, int);
ptr = 0;
numofbuffers--;
}
 
while(len)
{
if(len)
{
a = pdata[ptr++];
len--;
if((!len) && numofbuffers)
{
pdata = va_arg(ap, uint8_t*);
len = va_arg(ap, int);
ptr = 0;
numofbuffers--;
}
}
else a = 0;
if(len)
{
b = pdata[ptr++];
len--;
if((!len) && numofbuffers)
{
pdata = va_arg(ap, uint8_t*);
len = va_arg(ap, int);
ptr = 0;
numofbuffers--;
}
}
else b = 0;
if(len)
{
c = pdata[ptr++];
len--;
if((!len) && numofbuffers)
{
pdata = va_arg(ap, uint8_t*);
len = va_arg(ap, int);
ptr = 0;
numofbuffers--;
}
}
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);
}
va_end(ap);
AddCRC(pt); // add checksum after data block and initates the transmission
}
 
 
// --------------------------------------------------------------------------
void Decode64(void)
{
uint8_t a,b,c,d;
uint8_t x,y,z;
uint8_t ptrIn = 3;
uint8_t ptrOut = 3;
uint8_t len = ReceivedBytes - 6;
 
while(len)
{
a = rxd_buffer[ptrIn++] - '=';
b = rxd_buffer[ptrIn++] - '=';
c = rxd_buffer[ptrIn++] - '=';
d = rxd_buffer[ptrIn++] - '=';
//if(ptrIn > ReceivedBytes - 3) break;
 
x = (a << 2) | (b >> 4);
y = ((b & 0x0f) << 4) | (c >> 2);
z = ((c & 0x03) << 6) | d;
 
if(len--) rxd_buffer[ptrOut++] = x; else break;
if(len--) rxd_buffer[ptrOut++] = y; else break;
if(len--) rxd_buffer[ptrOut++] = z; else break;
}
pRxData = &rxd_buffer[3];
RxDataLen = ptrOut - 3;
}
 
 
 
// --------------------------------------------------------------------------
void USART0_Putchar (char c)
{
// if tx is not enabled return immediatly
if(!(UCSR0B & (1 << TXEN0))) return;
// wait until previous character was send
loop_until_bit_is_set(UCSR0A, UDRE0);
// send character
UDR0 = c;
}
 
 
// --------------------------------------------------------------------------
void USART0_ProcessRxData(void)
{
// if data in the rxd buffer are not locked immediately return
if(!rxd_buffer_locked) return;
 
Decode64(); // decode data block in rxd_buffer
 
switch(rxd_buffer[1]-'a') // check Slave Address
{
case MK3MAG_ADDRESS:
 
switch(rxd_buffer[2]) // check for CmdID
{
case 'w': // old style
case 'k': // Attitude info from FC
memcpy(&ExternData, (uint8_t*)pRxData, sizeof(ExternData));
RequestFlags |= RQST_COMPASS_HEADING;
#ifndef HEADTRACKER
AttitudeSource = ATTITUDE_SOURCE_UART;
#endif
Orientation = ExternData.Orientation;
FC_Connected = 255;
break;
 
default:
// unsupported command
break;
} // case MK3MAG_ADDRESS:
 
default: // any Slave Address
 
switch(rxd_buffer[2]) // check for CmdID
{
case 'b': // extern control
memcpy(&ExternControl, (uint8_t*)pRxData, sizeof(ExternControl));
#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;
}
ConfirmFrame = ExternControl.Frame;
PC_Connected = 2000;
break;
 
case 'd': // request for the debug data
DebugData_Interval = (uint16_t) pRxData[0] * 10;
if(DebugData_Interval>0) RequestFlags |= RQST_DEBUG_DATA;
PC_Connected = 2000;
break;
 
case 'v': // request version and board release
RequestFlags |= RQST_VERSION_INFO;
PC_Connected = 2000;
break;
 
case 'h': // request display data
if((pRxData[0] & 0x80) == 0x00) // old format
{
DisplayLine = 2;
Display_Interval = 0;
}
else
{
RemoteKeys |= ~pRxData[0];
Display_Interval = (uint16_t) pRxData[1] * 10;
DisplayLine = 4;
}
RequestFlags |= RQST_DISPLAY_DATA;
PC_Connected = 2000;
break;
 
case 'a':// Labels of the Analog Debug outputs
RequestDebugLabel = pRxData[0];
RequestFlags |= RQST_DEBUG_LABEL;
PC_Connected = 2000;
break;
 
case 'g':// get extern control data
RequestFlags |= RQST_EXTERN_CTRL;
PC_Connected = 2000;
break;
 
default:
// unsupported command
break;
}
break; // default:
}
// unlock the rxd buffer after processing
pRxData = 0;
RxDataLen = 0;
rxd_buffer_locked = FALSE;
}
 
 
 
//---------------------------------------------------------------------------------------------
void USART0_TransmitTxData(void)
{
if(!(UCSR0B & (1 << TXEN0))) return;
 
if(!txd_complete) return;
 
if((RequestFlags & RQST_DEBUG_LABEL))
{
uint8_t label[16];
memcpy_P(label, ANALOG_LABEL[RequestDebugLabel], 16); // read lable from flash to sram buffer
SendOutData('A', MK3MAG_ADDRESS, 2, (uint8_t *)&RequestDebugLabel, sizeof(RequestDebugLabel), label, 16);
RequestDebugLabel = 0xFF;
RequestFlags &= ~RQST_DEBUG_LABEL;
}
else if(ConfirmFrame)
{
SendOutData('B', MK3MAG_ADDRESS, 1, (uint8_t *) &ConfirmFrame, sizeof(ConfirmFrame));
ConfirmFrame = 0;
}
else if((((DebugData_Interval > 0) && CheckDelay(DebugData_Timer)) || (RequestFlags & RQST_DEBUG_DATA)))
{
SetDebugValues();
SendOutData('D', MK3MAG_ADDRESS, 1, (uint8_t *) &DebugOut, sizeof(DebugOut));
DebugData_Timer = SetDelay(DebugData_Interval);
RequestFlags &= ~RQST_DEBUG_DATA;
}
else if(( ((Display_Interval > 0) && CheckDelay(Display_Timer)) || (RequestFlags & RQST_DISPLAY_DATA)))
{
if(DisplayLine > 3)// new format
{
Menu_Update(RemoteKeys);
RemoteKeys = 0;
SendOutData('H', MK3MAG_ADDRESS, 1, (uint8_t *)DisplayBuff, 80);
}
else // old format
{
LCD_printfxy(0,0,"!!! INCOMPATIBLE !!!");
SendOutData('H', MK3MAG_ADDRESS, 2, &DisplayLine, sizeof(DisplayLine), (uint8_t *)DisplayBuff, 20);
if(DisplayLine++ > 3) DisplayLine = 0;
}
Display_Timer = SetDelay(Display_Interval);
RequestFlags &= ~RQST_DISPLAY_DATA;
}
else if((RequestFlags & RQST_EXTERN_CTRL))
{
SendOutData('G', MK3MAG_ADDRESS, 1, (uint8_t *) &ExternControl,sizeof(ExternControl));
RequestFlags &= ~RQST_EXTERN_CTRL;
}
else if((RequestFlags & RQST_COMPASS_HEADING))
{
SendOutData('K', FC_ADDRESS, 1, (uint8_t *) &Heading, sizeof(Heading)); // send compass heading to FC
RequestFlags &= ~RQST_COMPASS_HEADING;
}
else if((RequestFlags & RQST_VERSION_INFO))
{
SendOutData('V', MK3MAG_ADDRESS, 1, (uint8_t *) &UART_VersionInfo, sizeof(UART_VersionInfo));
RequestFlags &= ~RQST_VERSION_INFO;
}
#ifdef HEADTRACKER
else if((PotiIntervall > 0) && CheckDelay(PotiTimer))
{
SendOutData('y', FC_ADDRESS, 1, (uint8_t *) PotiToFC, sizeof(PotiToFC)); // send compass heading to FC
PotiTimer = SetDelay(PotiIntervall);
}
#endif
}
 
void USART0_Print(int8_t *msg)
{
uint8_t i = 0;
while(msg[i] != 0)
{
USART0_Putchar(msg[i++]);
}
}
/tags/V0.23a/Compassl.pnps
New file
0,0 → 1,0
<pd><ViewState><e p="avr_ctrl" x="true"></e></ViewState></pd>
/tags/V0.23a/License.txt
New file
0,0 → 1,59
/*#######################################################################################
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 / NON-COMMERCIAL USE ONLY
// + www.MikroKopter.com
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Die Portierung oder Nutzung 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 Portierung oder Nutzung der Software (oder Teile davon) auf andere Systeme (ausser der Hardware von www.mikrokopter.de) ist nur
// + mit unserer Zustimmung zulässig
/// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + 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 the sources to other systems or using the software on other systems (except 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.
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
/tags/V0.23a/uart.h
New file
0,0 → 1,78
#ifndef _UART_H_
#define _UART_H_
 
#include <inttypes.h>
#include "printf_P.h"
 
#define NICK 0
#define ROLL 1
 
 
#define BAUD_RATE 57600
 
 
extern uint16_t DebugData_Timer;
 
 
void USART0_Init (void);
void USART0_EnableTXD(void);
void USART0_DisableTXD(void);
void USART0_TransmitTxData(void);
void USART0_ProcessRxData(void);
void USART0_Putchar(char c);
void USART0_Print(int8_t *msg);
 
#define printf_P(format, args...) _printf_P(&USART0_Putchar, format , ## args)
#define printf(format, args...) _printf_P(&USART0_Putchar, PSTR(format) , ## args)
 
typedef struct
{
uint8_t Digital[2];
uint16_t Analog[32]; // Debugvalues
} DebugOut_t;
 
extern DebugOut_t DebugOut;
 
 
 
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;
 
extern ExternData_t ExternData;
 
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 free;
uint8_t Frame;
uint8_t Config;
} ExternControl_t;
 
extern ExternControl_t ExternControl;
 
 
typedef struct
{
uint8_t SWMajor;
uint8_t SWMinor;
uint8_t ProtoMajor;
uint8_t ProtoMinor;
uint8_t SWPatch;
uint8_t Reserved[5];
} UART_VersionInfo_t;
 
extern uint16_t PC_Connected;
extern uint16_t FC_Connected;
 
#endif //_UART_H_
/tags/V0.23a/printf_P.c
New file
0,0 → 1,469
// Die Funktion printf_P() unterliegt ihrer eigenen Lizenz und ist nicht von der Lizenz für den MikroKopter-Teil unterstellt
 
/*
Copyright (C) 1993 Free Software Foundation
 
This file is part of the GNU IO Library. This library is free
software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option)
any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this library; see the file COPYING. If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
As a special exception, if you link this library with files
compiled with a GNU compiler to produce an executable, this does not cause
the resulting executable to be covered by the GNU General Public License.
This exception does not however invalidate any other reasons why
the executable file might be covered by the GNU General Public License. */
 
/*
* Copyright (c) 1990 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. [rescinded 22 July 1999]
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
*/
 
/******************************************************************************
This file is a patched version of printf called _printf_P
It is made to work with avr-gcc for Atmel AVR MCUs.
There are some differences from standard printf:
1. There is no floating point support (with fp the code is about 8K!)
2. Return type is void
3. Format string must be in program memory (by using macro printf this is
done automaticaly)
4. %n is not implemented (just remove the comment around it if you need it)
5. If LIGHTPRINTF is defined, the code is about 550 bytes smaller and the
folowing specifiers are disabled :
space # * . - + p s o O
6. A function void uart_sendchar(char c) is used for output. The UART must
be initialized before using printf.
 
Alexander Popov
sasho@vip.orbitel.bg
******************************************************************************/
 
/*
* Actual printf innards.
*
* This code is large and complicated...
*/
 
#include <string.h>
#ifdef __STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif
 
#include "old_macros.h"
#include "printf_P.h"
 
 
void PRINT(pVoidFnctChar pPutchar, const char * ptr, unsigned int len)
{
for(;len;len--) (*pPutchar)(*ptr++);
}
 
void PRINTP(pVoidFnctChar pPutchar, const char * ptr, unsigned int len)
{
for(;len;len--) (*pPutchar)(pgm_read_byte(ptr++));
}
 
void PAD_SP(pVoidFnctChar pPutchar, signed char howmany)
{
for(;howmany>0;howmany--) (*pPutchar)(' ');
}
 
void PAD_0(pVoidFnctChar pPutchar, signed char howmany)
{
for(;howmany>0;howmany--) (*pPutchar)('0');
}
 
#define BUF 40
 
/*
* Macros for converting digits to letters and vice versa
*/
#define to_digit(c) ((c) - '0')
#define is_digit(c) ((c)<='9' && (c)>='0')
#define to_char(n) ((n) + '0')
 
/*
* Flags used during conversion.
*/
#define LONGINT 0x01 /* long integer */
#define LONGDBL 0x02 /* long double; unimplemented */
#define SHORTINT 0x04 /* short integer */
#define ALT 0x08 /* alternate form */
#define LADJUST 0x10 /* left adjustment */
#define ZEROPAD 0x20 /* zero (as opposed to blank) pad */
#define HEXPREFIX 0x40 /* add 0x or 0X prefix */
 
void _printf_P (pVoidFnctChar pPutchar, char const *fmt0, ...) /* Works with string from FLASH */
{
va_list ap;
register const char *fmt; /* format string */
register char ch; /* character from fmt */
register int n; /* handy integer (short term usage) */
register char *cp; /* handy char pointer (short term usage) */
const char *fmark; /* for remembering a place in fmt */
register unsigned char flags; /* flags as above */
signed char width; /* width from format (%8d), or 0 */
signed char prec; /* precision from format (%.3d), or -1 */
char sign; /* sign prefix (' ', '+', '-', or \0) */
unsigned long _ulong=0; /* integer arguments %[diouxX] */
#define OCT 8
#define DEC 10
#define HEX 16
unsigned char base; /* base for [diouxX] conversion */
signed char dprec; /* a copy of prec if [diouxX], 0 otherwise */
signed char dpad; /* extra 0 padding needed for integers */
signed char fieldsz; /* field size expanded by sign, dpad etc */
/* The initialization of 'size' is to suppress a warning that
'size' might be used unitialized. It seems gcc can't
quite grok this spaghetti code ... */
signed char size = 0; /* size of converted field or string */
char buf[BUF]; /* space for %c, %[diouxX], %[eEfgG] */
char ox[2]; /* space for 0x hex-prefix */
 
va_start(ap, fmt0);
 
fmt = fmt0;
 
/*
* Scan the format for conversions (`%' character).
*/
for (;;) {
for (fmark = fmt; (ch = pgm_read_byte(fmt)) != '\0' && ch != '%'; fmt++)
/* void */;
if ((n = fmt - fmark) != 0) {
PRINTP(pPutchar, fmark, n);
}
if (ch == '\0')
goto done;
fmt++; /* skip over '%' */
 
flags = 0;
dprec = 0;
width = 0;
prec = -1;
sign = '\0';
 
rflag: ch = PRG_RDB(fmt++);
reswitch:
#ifdef LIGHTPRINTF
if (ch=='o' || ch=='u' || (ch|0x20)=='x') {
#else
if (ch=='u' || (ch|0x20)=='x') {
#endif
if (flags&LONGINT) {
_ulong=va_arg(ap, unsigned long);
} else {
register unsigned int _d;
_d=va_arg(ap, unsigned int);
_ulong = flags&SHORTINT ? (unsigned long)(unsigned short)_d : (unsigned long)_d;
}
}
 
#ifndef LIGHTPRINTF
if(ch==' ') {
/*
* ``If the space and + flags both appear, the space
* flag will be ignored.''
* -- ANSI X3J11
*/
if (!sign)
sign = ' ';
goto rflag;
} else if (ch=='#') {
flags |= ALT;
goto rflag;
} else if (ch=='*'||ch=='-') {
if (ch=='*') {
/*
* ``A negative field width argument is taken as a
* - flag followed by a positive field width.''
* -- ANSI X3J11
* They don't exclude field widths read from args.
*/
if ((width = va_arg(ap, int)) >= 0)
goto rflag;
width = -width;
}
flags |= LADJUST;
flags &= ~ZEROPAD; /* '-' disables '0' */
goto rflag;
} else if (ch=='+') {
sign = '+';
goto rflag;
} else if (ch=='.') {
if ((ch = PRG_RDB(fmt++)) == '*') {
n = va_arg(ap, int);
prec = n < 0 ? -1 : n;
goto rflag;
}
n = 0;
while (is_digit(ch)) {
n = n*10 + to_digit(ch);
ch = PRG_RDB(fmt++);
}
prec = n < 0 ? -1 : n;
goto reswitch;
} else
#endif /* LIGHTPRINTF */
if (ch=='0') {
/*
* ``Note that 0 is taken as a flag, not as the
* beginning of a field width.''
* -- ANSI X3J11
*/
if (!(flags & LADJUST))
flags |= ZEROPAD; /* '-' disables '0' */
goto rflag;
} else if (ch>='1' && ch<='9') {
n = 0;
do {
n = 10 * n + to_digit(ch);
ch = PRG_RDB(fmt++);
} while (is_digit(ch));
width = n;
goto reswitch;
} else if (ch=='h') {
flags |= SHORTINT;
goto rflag;
} else if (ch=='l') {
flags |= LONGINT;
goto rflag;
} else if (ch=='c') {
*(cp = buf) = va_arg(ap, int);
size = 1;
sign = '\0';
} else if (ch=='D'||ch=='d'||ch=='i') {
if(ch=='D')
flags |= LONGINT;
if (flags&LONGINT) {
_ulong=va_arg(ap, long);
} else {
register int _d;
_d=va_arg(ap, int);
_ulong = flags&SHORTINT ? (long)(short)_d : (long)_d;
}
 
if ((long)_ulong < 0) {
_ulong = -_ulong;
sign = '-';
}
base = DEC;
goto number;
} else
/*
if (ch=='n') {
if (flags & LONGINT)
*va_arg(ap, long *) = ret;
else if (flags & SHORTINT)
*va_arg(ap, short *) = ret;
else
*va_arg(ap, int *) = ret;
continue; // no output
} else
*/
#ifndef LIGHTPRINTF
if (ch=='O'||ch=='o') {
if (ch=='O')
flags |= LONGINT;
base = OCT;
goto nosign;
} else if (ch=='p') {
/*
* ``The argument shall be a pointer to void. The
* value of the pointer is converted to a sequence
* of printable characters, in an implementation-
* defined manner.''
* -- ANSI X3J11
*/
/* NOSTRICT */
_ulong = (unsigned int)va_arg(ap, void *);
base = HEX;
flags |= HEXPREFIX;
ch = 'x';
goto nosign;
} else if (ch=='s') { // print a string from RAM
if ((cp = va_arg(ap, char *)) == NULL) {
cp=buf;
cp[0] = '(';
cp[1] = 'n';
cp[2] = 'u';
cp[4] = cp[3] = 'l';
cp[5] = ')';
cp[6] = '\0';
}
if (prec >= 0) {
/*
* can't use strlen; can only look for the
* NUL in the first `prec' characters, and
* strlen() will go further.
*/
char *p = (char*)memchr(cp, 0, prec);
 
if (p != NULL) {
size = p - cp;
if (size > prec)
size = prec;
} else
size = prec;
} else
size = strlen(cp);
sign = '\0';
} else
#endif /* LIGHTPRINTF */
if(ch=='U'||ch=='u') {
if (ch=='U')
flags |= LONGINT;
base = DEC;
goto nosign;
} else if (ch=='X'||ch=='x') {
base = HEX;
/* leading 0x/X only if non-zero */
if (flags & ALT && _ulong != 0)
flags |= HEXPREFIX;
 
/* unsigned conversions */
nosign: sign = '\0';
/*
* ``... diouXx conversions ... if a precision is
* specified, the 0 flag will be ignored.''
* -- ANSI X3J11
*/
number: if ((dprec = prec) >= 0)
flags &= ~ZEROPAD;
 
/*
* ``The result of converting a zero value with an
* explicit precision of zero is no characters.''
* -- ANSI X3J11
*/
cp = buf + BUF;
if (_ulong != 0 || prec != 0) {
register unsigned char _d,notlastdigit;
do {
notlastdigit=(_ulong>=base);
_d = _ulong % base;
 
if (_d<10) {
_d+='0';
} else {
_d+='a'-10;
if (ch=='X') _d&=~0x20;
}
*--cp=_d;
_ulong /= base;
} while (notlastdigit);
#ifndef LIGHTPRINTF
// handle octal leading 0
if (base==OCT && flags & ALT && *cp != '0')
*--cp = '0';
#endif
}
 
size = buf + BUF - cp;
} else { //default
/* "%?" prints ?, unless ? is NUL */
if (ch == '\0')
goto done;
/* pretend it was %c with argument ch */
cp = buf;
*cp = ch;
size = 1;
sign = '\0';
}
 
/*
* All reasonable formats wind up here. At this point,
* `cp' points to a string which (if not flags&LADJUST)
* should be padded out to `width' places. If
* flags&ZEROPAD, it should first be prefixed by any
* sign or other prefix; otherwise, it should be blank
* padded before the prefix is emitted. After any
* left-hand padding and prefixing, emit zeroes
* required by a decimal [diouxX] precision, then print
* the string proper, then emit zeroes required by any
* leftover floating precision; finally, if LADJUST,
* pad with blanks.
*/
 
/*
* compute actual size, so we know how much to pad.
*/
fieldsz = size;
 
dpad = dprec - size;
if (dpad < 0)
dpad = 0;
 
if (sign)
fieldsz++;
else if (flags & HEXPREFIX)
fieldsz += 2;
fieldsz += dpad;
 
/* right-adjusting blank padding */
if ((flags & (LADJUST|ZEROPAD)) == 0)
PAD_SP(pPutchar, width - fieldsz);
 
/* prefix */
if (sign) {
PRINT(pPutchar, &sign, 1);
} else if (flags & HEXPREFIX) {
ox[0] = '0';
ox[1] = ch;
PRINT(pPutchar, ox, 2);
}
 
/* right-adjusting zero padding */
if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
PAD_0(pPutchar, width - fieldsz);
 
/* leading zeroes from decimal precision */
PAD_0(pPutchar, dpad);
 
/* the string or number proper */
PRINT(pPutchar, cp, size);
 
/* left-adjusting padding (always blank) */
if (flags & LADJUST)
PAD_SP(pPutchar, width - fieldsz);
}
done:
va_end(ap);
}
/tags/V0.23a/main.c
New file
0,0 → 1,572
/*#######################################################################################
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 / NON-COMMERCIAL USE ONLY
// + www.MikroKopter.com
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Die Portierung oder Nutzung 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 the sources to other systems or using the software on other systems (except 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 <avr/interrupt.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
 
#include "main.h"
#include "timer0.h"
#include "twislave.h"
#include "led.h"
#include "analog.h"
#include "uart.h"
 
#define CALIBRATION_VERSION 1
 
AttitudeSource_t AttitudeSource = ATTITUDE_SOURCE_ACC;
Orientation_t Orientation = ORIENTATION_FC;
 
uint16_t Led_Timer = 0;
 
typedef struct
{
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;
uint8_t Version;
} 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
int16_t ZeroHeading = 180;
uint8_t InternalCalstate = 0, ActualCalstate = 0;
int8_t PotiToFC[12] = {0,0,0,0,0,0,0,0,0,0,0,0};
 
void CalcFields(void)
{
UncalMagX = (RawMagnet1a - RawMagnet1b);
UncalMagY = (RawMagnet3a - RawMagnet3b);
UncalMagZ = (RawMagnet2a - RawMagnet2b);
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;
if(AttitudeSource == ATTITUDE_SOURCE_ACC)
{
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, Cx = 0, Cy = 0, Cz = 0, Hx = 0, Hy = 0;
int16_t nick, roll;
int16_t heading = -1;
 
// blink code for normal operation
if(CheckDelay(Led_Timer))
{
if(Calibration.Version != CALIBRATION_VERSION) LED_GRN_TOGGLE;
else LED_GRN_ON;
Led_Timer = SetDelay(150);
}
 
if(Calibration.Version != CALIBRATION_VERSION) heading = -1; // Version of the calibration Data does not match
else
{
switch(Orientation)
{
case ORIENTATION_NC:
Cx = (double)MagX;
Cy = (double)MagY;
Cz = (double)MagZ;
break;
 
case ORIENTATION_FC:
// rotation of 90 deg compared to NC setup
Cx = (double)MagY;
Cy = -(double)MagX;
Cz = (double)MagZ;
break;
}
#ifdef HEADTRACKER
AttitudeSource = ATTITUDE_SOURCE_ACC;
#endif
// 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 = 0;
roll = 0;
break;
}
 
nick_rad = ((double)nick * M_PI) / 1800.0;
roll_rad = ((double)roll * M_PI) / 1800.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;
}
// stop interrrupts during heading update to avoid transmitting heading between the update of both bytes of the int16_t
cli(); // stop interrupts
if(abs(heading) < 361) Heading = heading;
else (Heading = -1);
sei(); // start interrupts
}
 
void Calibrate(void)
{
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;
 
if(ActualCalstate > 5) ActualCalstate = 0;
// blink code for current calibration state
if(ActualCalstate)
{
if(CheckDelay(Led_Timer) || (ActualCalstate != 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 * ActualCalstate))
{
blinkcount = 0;
Led_Timer = SetDelay(1500);
}
else
{
blinkcount++;
Led_Timer = SetDelay(100);
}
}
}
else
{
if(invert_blinking) LED_GRN_ON; else LED_GRN_OFF;
}
// calibration state machine
switch(ActualCalstate)
{
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(ActualCalstate != 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))
{
Calibration.Version = CALIBRATION_VERSION;
// indicate write process by setting the led off for 2 seconds
LED_GRN_OFF;
eeprom_write_block(&Calibration, &eeCalibration, sizeof(Calibration));
Led_Timer = SetDelay(2000);
// reset blinkcode
blinkcount = 0;
}
else
{
// restore old calibration data from eeprom
eeprom_read_block(&Calibration, &eeCalibration, sizeof(Calibration));
}
}
invert_blinking = 0;
break;
 
default:
break;
}
calold = ActualCalstate;
}
 
 
void SetDebugValues(void)
{
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;
default:
DebugOut.Analog[6] = -1;
DebugOut.Analog[7] = -1;
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] = ActualCalstate;
DebugOut.Analog[15] = Heading;
DebugOut.Analog[16] = 0;
DebugOut.Analog[17] = 0;
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] = PotiToFC[0];
DebugOut.Analog[25] = PotiToFC[1];
DebugOut.Analog[26] = PotiToFC[2];
DebugOut.Analog[29] = AttitudeSource;
}
 
void AccMeasurement(void)
{
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;
}
}
 
#ifdef HEADTRACKER
void CalcFcPotis(void)
{
int16_t tmp0, tmp1, tmp2;
if(AccPresent)
{
tmp0 = AccAttitudeNick/4;
tmp1 = AccAttitudeRoll/4;
tmp2 = (360 + Heading - ZeroHeading) % 360;
tmp2 -= 180;
tmp2 *= 2;
if(tmp0 > 127) tmp0 = 127; else if(tmp0 < -127) tmp0 = -127;
if(tmp1 > 127) tmp1 = 127; else if(tmp1 < -127) tmp1 = -127;
if(tmp2 > 127) tmp2 = 127; else if(tmp2 < -127) tmp2 = -127;
PotiToFC[0] = (PotiToFC[0] + tmp0) / 2;
PotiToFC[1] = (PotiToFC[1] + tmp1) / 2;
PotiToFC[2] = (PotiToFC[2] + tmp2) / 2;
}
}
#endif
 
int main (void)
{
static uint8_t state = 0;
static uint16_t statetimer;
// reset input pullup
DDRC &=~((1<<DDC6));
PORTC |= (1<<PORTC6);
 
LED_Init();
TIMER0_Init();
USART0_Init();
ADC_Init();
I2C_Init();
 
sei(); // enable globale interrupts
USART0_Print("\n\rthe use of this software is only permitted\n\ron original MikroKopter-Hardware");
USART0_Print("\n\rwww.MikroKopter.de (c) HiSystems GmbH\n\n");
#ifdef HEADTRACKER
USART0_Print("\n\rHead-Tracker");
#endif
if(AccPresent)
{
USART0_Print("\r\rACC present");
}
#ifdef HEADTRACKER
else USART0_Print("\n\rERROR: NO ACC");
#endif
 
LED_GRN_ON;
 
Led_Timer = SetDelay(200);
 
// read calibration info from eeprom
eeprom_read_block(&Calibration, &eeCalibration, sizeof(Calibration));
 
InternalCalstate = 0;
ExternData.CalState = 0;
I2C_WriteCal.CalByte = 0;
ActualCalstate = 0;
statetimer = SetDelay(0);
// main loop
while (1)
{
 
switch(state)
{
case 0:
if(CheckDelay(statetimer))
{
FLIP_LOW;
statetimer = SetDelay(2);
state = 1;
}
break;
 
case 1:
if(CheckDelay(statetimer))
{
RawMagnet1a = ADC_GetValue(MAG_X);
RawMagnet2a = -ADC_GetValue(MAG_Y);
RawMagnet3a = ADC_GetValue(MAG_Z);
AccMeasurement();
statetimer = SetDelay(1);
state = 2;
}
break;
 
case 2:
if(CheckDelay(statetimer))
{
FLIP_HIGH;
statetimer = SetDelay(2);
state = 3;
}
break;
 
case 3:
if(CheckDelay(statetimer))
{
RawMagnet1b = ADC_GetValue(MAG_X);
RawMagnet2b = -ADC_GetValue(MAG_Y);
RawMagnet3b = ADC_GetValue(MAG_Z);
AccMeasurement();
statetimer = SetDelay(1);
state = 0;
CalcFields();
// check both sources of communication for calibration request
if(InternalCalstate) ActualCalstate = InternalCalstate;
else
if(I2C_WriteCal.CalByte) ActualCalstate = I2C_WriteCal.CalByte;
else ActualCalstate = ExternData.CalState;
if(ActualCalstate) Calibrate();
else CalcHeading();
if(NC_Connected) NC_Connected--;
if(FC_Connected) FC_Connected--;
if(PC_Connected) PC_Connected--;
// fall back to attitude estimation from onboard acc sensor if NC or FC does'nt send attitude data
#ifdef HEADTRACKER
CalcFcPotis();
if(AccPresent) AttitudeSource = ATTITUDE_SOURCE_ACC;
#else
if(!FC_Connected && ! NC_Connected)
{
if(AccPresent) AttitudeSource = ATTITUDE_SOURCE_ACC;
else AttitudeSource = ATTITUDE_SOURCE_NONE;
Orientation = ORIENTATION_FC;
}
#endif
}
break;
 
default: // should never happen
statetimer = SetDelay(0);
state = 0;
break;
} // one full state cylce is 6 ms
 
// check data from USART
USART0_ProcessRxData();
#ifdef HEADTRACKER
USART0_TransmitTxData();
#else
if(PC_Connected)
{
USART0_EnableTXD();
USART0_TransmitTxData();
}
else
{
USART0_DisableTXD();
}
#endif
} // while(1)
}
 
/tags/V0.23a/printf_P.h
New file
0,0 → 1,11
#ifndef _PRINTF_P_H_
#define _PRINTF_P_H_
 
#include <avr/pgmspace.h>
 
// function pointer to external callback put character function
typedef void (*pVoidFnctChar) (char );
 
void _printf_P (pVoidFnctChar pPutchar, char const *fmt0, ...);
 
#endif //_PRINTF_P_H_
/tags/V0.23a/old_macros.h
New file
0,0 → 1,47
/*
For backwards compatibility only.
Ingo Busker ingo@mikrocontroller.com
*/
 
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
 
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
 
#ifndef inb
#define inb(sfr) _SFR_BYTE(sfr)
#endif
 
#ifndef outb
#define outb(sfr, val) (_SFR_BYTE(sfr) = (val))
#endif
 
#ifndef inw
#define inw(sfr) _SFR_WORD(sfr)
#endif
 
#ifndef outw
#define outw(sfr, val) (_SFR_WORD(sfr) = (val))
#endif
 
#ifndef outp
#define outp(val, sfr) outb(sfr, val)
#endif
 
#ifndef inp
#define inp(sfr) inb(sfr)
#endif
 
#ifndef BV
#define BV(bit) _BV(bit)
#endif
 
 
#ifndef PRG_RDB
#define PRG_RDB pgm_read_byte
#endif
 
/tags/V0.23a/main.h
New file
0,0 → 1,36
#ifndef _MAIN_H_
#define _MAIN_H_
 
 
#include <avr/eeprom.h>
#include <inttypes.h>
 
 
typedef enum
{
ATTITUDE_SOURCE_I2C = 0,
ATTITUDE_SOURCE_UART = 1,
ATTITUDE_SOURCE_ACC = 2,
ATTITUDE_SOURCE_NONE = 3
} AttitudeSource_t;
 
 
typedef enum
{
ORIENTATION_NC = 0,
ORIENTATION_FC = 1
} Orientation_t;
 
 
extern int16_t Heading;
 
extern AttitudeSource_t AttitudeSource;
extern Orientation_t Orientation;
extern uint8_t InternalCalstate, ActualCalstate;
 
extern int16_t MagX, MagY, MagZ;
extern int8_t PotiToFC[12];
void SetDebugValues(void);
 
#endif //_MAIN_H_
 
/tags/V0.23a/Compass.pnproj
New file
0,0 → 1,0
<Project name="avr_ctrl"><File path="uart.h"></File><File path="main.c"></File><File path="main.h"></File><File path="makefile"></File><File path="uart.c"></File><File path="timer0.c"></File><File path="timer0.h"></File><File path="analog.h"></File><File path="analog.c"></File><File path="twislave.c"></File><File path="twislave.h"></File><File path="menu.c"></File></Project>
/tags/V0.23a/makefile
New file
0,0 → 1,429
#--------------------------------------------------------------------
# MCU name
MCU = atmega168
F_CPU = 8000000
#-------------------------------------------------------------------
#BOARD = 10
BOARD = 11
#OPTION = HEADTRACKER
 
VERSION_MAJOR = 0
VERSION_MINOR = 23
VERSION_PATCH = 0
 
VERSION_SERIAL_MAJOR = 11 # Serial Protocol Major Version
VERSION_SERIAL_MINOR = 0 # Serial Protocol Minor Version
NC_I2C_COMPATIBLE = 3 # I2C Protocol Version
#-------------------------------------------------------------------
 
# get SVN revision
REV := $(shell sh -c "cat .svn/entries | sed -n '4p'")
 
# Output format. (can be srec, ihex, binary)
FORMAT = ihex
 
# Target file name (without extension).
 
ifeq ($(VERSION_PATCH), 0)
TARGET = MK3Mag_MEGA168_V$(VERSION_MAJOR)_$(VERSION_MINOR)a_SVN$(REV)
endif
ifeq ($(VERSION_PATCH), 1)
TARGET = MK3Mag_MEGA168_V$(VERSION_MAJOR)_$(VERSION_MINOR)b_SVN$(REV)
endif
ifeq ($(VERSION_PATCH), 2)
TARGET = MK3Mag_MEGA168_V$(VERSION_MAJOR)_$(VERSION_MINOR)c_SVN$(REV)
endif
ifeq ($(VERSION_PATCH), 3)
TARGET = MK3Mag_MEGA168_V$(VERSION_MAJOR)_$(VERSION_MINOR)d_SVN$(REV)
endif
ifeq ($(VERSION_PATCH), 4)
TARGET = MK3Mag_MEGA168_V$(VERSION_MAJOR)_$(VERSION_MINOR)e_SVN$(REV)
endif
ifeq ($(VERSION_PATCH), 5)
TARGET = MK3Mag_MEGA168_V$(VERSION_MAJOR)_$(VERSION_MINOR)f_SVN$(REV)
endif
ifeq ($(VERSION_PATCH), 6)
TARGET = MK3Mag_MEGA168_V$(VERSION_MAJOR)_$(VERSION_MINOR)g_SVN$(REV)
endif
ifeq ($(VERSION_PATCH), 7)
TARGET = MK3Mag_MEGA168_V$(VERSION_MAJOR)_$(VERSION_MINOR)h_SVN$(REV)
endif
ifeq ($(VERSION_PATCH), 8)
TARGET = MK3Mag_MEGA168_V$(VERSION_MAJOR)_$(VERSION_MINOR)i_SVN$(REV)
endif
ifeq ($(VERSION_PATCH), 9)
TARGET = MK3Mag_MEGA168_V$(VERSION_MAJOR)_$(VERSION_MINOR)j_SVN$(REV)
endif
 
 
# 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.)
OPT = s
 
##########################################################################################################
# List C source files here. (C dependencies are automatically generated.)
SRC = main.c uart.c timer0.c analog.c twislave.c led.c menu.c printf_P.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
# output from the compiler), and will be deleted upon "make clean"!
# Even though the DOS/Win* filesystem matches both .s and .S the same,
# it will preserve the spelling of the filenames, and gcc itself does
# care about how the name is spelled on its command-line.
ASRC =
 
 
# List any extra directories to look for include files here.
# Each directory must be seperated by a space.
EXTRAINCDIRS =
 
 
CDEFS = -DF_CPU=$(F_CPU)UL
 
# Optional compiler flags.
# -g: generate debugging information (for GDB, or for COFF conversion)
# -O*: optimization level
# -f...: tuning, see gcc manual and avr-libc documentation
# -Wall...: warning level
# -Wa,...: tell GCC to pass this to the assembler.
# -ahlms: create assembler listing
CFLAGS = -O$(OPT) \
-funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums \
-Wall -Wstrict-prototypes \
-Wa,-adhlns=$(<:.c=.lst) \
$(patsubst %,-I%,$(EXTRAINCDIRS))
 
 
# Set a "language standard" compiler flag.
# Unremark just one line below to set the language standard to use.
# gnu99 = C99 + GNU extensions. See GCC manual for more information.
#CFLAGS += -std=c89
#CFLAGS += -std=gnu89
#CFLAGS += -std=c99
CFLAGS += -std=gnu99
CFLAGS += $(CDEFS)
 
# shrink code size
CFLAGS += -mtiny-stack
#CFLAGS += -fno-inline-functions
CFLAGS += -mcall-prologues
 
CFLAGS += -DVERSION_MAJOR=$(VERSION_MAJOR) -DVERSION_MINOR=$(VERSION_MINOR) -DVERSION_PATCH=$(VERSION_PATCH) -DVERSION_SERIAL_MAJOR=$(VERSION_SERIAL_MAJOR) -DVERSION_SERIAL_MINOR=$(VERSION_SERIAL_MINOR) -DBOARD=$(BOARD) -DNC_I2C_COMPATIBLE=$(NC_I2C_COMPATIBLE)
 
ifeq ($(OPTION), HEADTRACKER)
CFLAGS += -DHEADTRACKER
endif
 
 
 
# Optional assembler flags.
# -Wa,...: tell GCC to pass this to the assembler.
# -ahlms: create listing
# -gstabs: have the assembler create line number information; note that
# for use in COFF files, additional information about filenames
# and function names needs to be present in the assembler source
# files -- see avr-libc docs [FIXME: not yet described there]
ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs
 
 
 
# Optional linker flags.
# -Wl,...: tell GCC to pass this to linker.
# -Map: create map file
# --cref: add cross reference to map file
LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
 
 
 
# Additional libraries
 
# Minimalistic printf version
#LDFLAGS += -Wl,-u,vfprintf -lprintf_min
 
# Floating point printf version (requires -lm below)
#LDFLAGS += -Wl,-u,vfprintf -lprintf_flt
 
# -lm = math library
LDFLAGS += -lm
 
 
 
 
# Programming support using avrdude. Settings and variables.
 
# Programming hardware: alf avr910 avrisp bascom bsd
# dt006 pavr picoweb pony-stk200 sp12 stk200 stk500
#
# Type: avrdude -c ?
# to get a full listing.
#
 
AVRDUDE_PROGRAMMER = dt006
#AVRDUDE_PROGRAMMER = stk200
 
#AVRDUDE_PORT = com1 # programmer connected to serial device
AVRDUDE_PORT = lpt1 # programmer connected to parallel port
 
AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex
#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep
 
AVRDUDE_FLAGS = -F -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
 
# Uncomment the following if you want avrdude's erase cycle counter.
# Note that this counter needs to be initialized first using -Yn,
# see avrdude manual.
#AVRDUDE_ERASE += -y
 
# Uncomment the following if you do /not/ wish a verification to be
# performed after programming the device.
#AVRDUDE_FLAGS += -V -E noreset
 
 
# Increase verbosity level. Please use this when submitting bug
# reports about avrdude. See <http://savannah.nongnu.org/projects/avrdude>
# to submit bug reports.
#AVRDUDE_FLAGS += -v -v
 
 
 
 
# ---------------------------------------------------------------------------
 
# Define directories, if needed.
DIRAVR = c:/winavr
DIRAVRBIN = $(DIRAVR)/bin
DIRAVRUTILS = $(DIRAVR)/utils/bin
DIRINC = .
DIRLIB = $(DIRAVR)/avr/lib
 
 
# Define programs and commands.
SHELL = sh
 
CC = avr-gcc
 
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
SIZE = avr-size
 
 
# Programming support using avrdude.
AVRDUDE = avrdude
 
 
REMOVE = rm -f
COPY = cp
 
HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
ELFSIZE = $(SIZE) -A $(TARGET).elf
LIMITS = $(SIZE) --mcu=$(MCU) -C $(TARGET).elf
 
 
 
# Define Messages
# English
MSG_ERRORS_NONE = Errors: none
MSG_BEGIN = -------- begin --------
MSG_END = -------- end --------
MSG_SIZE_BEFORE = Size before:
MSG_SIZE_AFTER = Size after:
MSG_COFF = Converting to AVR COFF:
MSG_EXTENDED_COFF = Converting to AVR Extended COFF:
MSG_FLASH = Creating load file for Flash:
MSG_EEPROM = Creating load file for EEPROM:
MSG_EXTENDED_LISTING = Creating Extended Listing:
MSG_SYMBOL_TABLE = Creating Symbol Table:
MSG_LINKING = Linking:
MSG_COMPILING = Compiling:
MSG_ASSEMBLING = Assembling:
MSG_CLEANING = Cleaning project:
 
 
 
 
# Define all object files.
OBJ = $(SRC:.c=.o) $(ASRC:.S=.o)
 
# Define all listing files.
LST = $(ASRC:.S=.lst) $(SRC:.c=.lst)
 
# Combine all necessary flags and optional flags.
# Add target processor to flags.
ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS)
ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
 
 
 
# Default target.
all: begin gccversion sizebefore $(TARGET).elf $(TARGET).hex $(TARGET).eep \
$(TARGET).lss $(TARGET).sym sizeafter finished end
 
 
# Eye candy.
# AVR Studio 3.x does not check make's exit code but relies on
# the following magic strings to be generated by the compile job.
begin:
@echo
@echo $(MSG_BEGIN)
 
finished:
@echo $(MSG_ERRORS_NONE)
 
end:
@echo $(MSG_END)
@echo
 
 
# Display size of file.
sizebefore:
@if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); $(LIMITS); echo; fi
 
sizeafter:
@if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); $(LIMITS); echo; fi
 
 
 
# Display compiler version information.
gccversion :
@$(CC) --version
 
 
 
 
# Convert ELF to COFF for use in debugging / simulating in
# AVR Studio or VMLAB.
COFFCONVERT=$(OBJCOPY) --debugging \
--change-section-address .data-0x800000 \
--change-section-address .bss-0x800000 \
--change-section-address .noinit-0x800000 \
--change-section-address .eeprom-0x810000
 
 
coff: $(TARGET).elf
@echo
@echo $(MSG_COFF) $(TARGET).cof
$(COFFCONVERT) -O coff-avr $< $(TARGET).cof
 
 
extcoff: $(TARGET).elf
@echo
@echo $(MSG_EXTENDED_COFF) $(TARGET).cof
$(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof
 
 
 
 
# Program the device.
program: $(TARGET).hex $(TARGET).eep
$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)
 
 
 
 
# Create final output files (.hex, .eep) from ELF output file.
%.hex: %.elf
@echo
@echo $(MSG_FLASH) $@
$(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
 
%.eep: %.elf
@echo
@echo $(MSG_EEPROM) $@
-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
--change-section-lma .eeprom=0 -O $(FORMAT) $< $@
 
# Create extended listing file from ELF output file.
%.lss: %.elf
@echo
@echo $(MSG_EXTENDED_LISTING) $@
$(OBJDUMP) -h -S $< > $@
 
# Create a symbol table from ELF output file.
%.sym: %.elf
@echo
@echo $(MSG_SYMBOL_TABLE) $@
avr-nm -n $< > $@
 
 
 
# Link: create ELF output file from object files.
.SECONDARY : $(TARGET).elf
.PRECIOUS : $(OBJ)
%.elf: $(OBJ)
@echo
@echo $(MSG_LINKING) $@
$(CC) $(ALL_CFLAGS) $(OBJ) --output $@ $(LDFLAGS)
 
 
# Compile: create object files from C source files.
%.o : %.c
@echo
@echo $(MSG_COMPILING) $<
$(CC) -c $(ALL_CFLAGS) $< -o $@
 
 
# Compile: create assembler files from C source files.
%.s : %.c
$(CC) -S $(ALL_CFLAGS) $< -o $@
 
 
# Assemble: create object files from assembler source files.
%.o : %.S
@echo
@echo $(MSG_ASSEMBLING) $<
$(CC) -c $(ALL_ASFLAGS) $< -o $@
 
 
 
 
 
 
# Target: clean project.
clean: begin clean_list finished end
 
clean_list :
@echo
@echo $(MSG_CLEANING)
$(REMOVE) MK3Mag_*.hex
$(REMOVE) MK3Mag_*.eep
$(REMOVE) $(TARGET).obj
$(REMOVE) $(TARGET).cof
$(REMOVE) MK3Mag_*.elf
$(REMOVE) MK3Mag_*.map
$(REMOVE) $(TARGET).obj
$(REMOVE) $(TARGET).a90
$(REMOVE) MK3Mag_*.sym
$(REMOVE) $(TARGET).lnk
$(REMOVE) MK3Mag_*.lss
$(REMOVE) $(OBJ)
$(REMOVE) $(LST)
$(REMOVE) $(SRC:.c=.s)
$(REMOVE) $(SRC:.c=.d)
 
 
# Automatically generate C source code dependencies.
# (Code originally taken from the GNU make user manual and modified
# (See README.txt Credits).)
#
# Note that this will work with sh (bash) and sed that is shipped with WinAVR
# (see the SHELL variable defined above).
# This may not work with other shells or other seds.
#
%.d: %.c
set -e; $(CC) -MM $(ALL_CFLAGS) $< \
| sed 's,\(.*\)\.o[ :]*,\1.o \1.d : ,g' > $@; \
[ -s $@ ] || rm -f $@
 
 
# Remove the '-' if you want to see the dependency files generated.
-include $(SRC:.c=.d)
 
 
 
# Listing of phony targets.
.PHONY : all begin finish end sizebefore sizeafter gccversion coff extcoff \
clean clean_list program
 
/tags/V0.23a/twislave.c
New file
0,0 → 1,289
/*#######################################################################################
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 / NON-COMMERCIAL USE ONLY
// + www.MikroKopter.com
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Die Portierung oder Nutzung 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 Portierung oder Nutzung der Software (oder Teile davon) auf andere Systeme (ausser der Hardware von www.mikrokopter.de) ist nur
// + mit unserer Zustimmung zulässig
/// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + 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 the sources to other systems or using the software on other systems (except 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 <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"
 
 
volatile uint8_t I2C_RxBufferSize = 0, I2C_TxBufferSize = 0;
volatile uint8_t *I2C_TxBuffer = 0, *I2C_RxBuffer = 0;
 
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;
 
// 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)
 
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;
I2C_TxBufferSize = 0;
I2C_RxBuffer = 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.Patch = VERSION_PATCH;
I2C_Version.Compatible = NC_I2C_COMPATIBLE;
TWCR_RESET;
// resore status register
SREG = sreg;
}
 
 
ISR (TWI_vect)
{
uint8_t data;
static uint8_t crc, Tx_Idx = 0, Rx_Idx = 0;
static uint8_t I2C_PrimRxBuffer[10];
// 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;
 
case TW_SR_DATA_ACK: // data has been received and ack has been returned
data = TWDR;
if (Rx_Idx == 0xFF)
{ // if the first 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_CAL:
I2C_TxBuffer = (uint8_t *)&I2C_WriteCal;
I2C_TxBufferSize = sizeof(I2C_WriteCal);
I2C_RxBuffer = (uint8_t *)&I2C_WriteCal;
I2C_RxBufferSize = sizeof(I2C_WriteCal);
break;
 
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 = 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 = (uint8_t *)&I2C_WriteAttitude;
I2C_RxBufferSize = sizeof(I2C_WriteAttitude);
I2C_Heading.Heading = Heading; // get heading
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
crc = ~crc; //flip all bits inthe checksum
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))
{
data = I2C_TxBuffer[Tx_Idx];
crc += data;
}
else if (Tx_Idx == I2C_TxBufferSize)
{ // send crc byte at the end
data = ~crc;
}
else
{
data = 0x00;
}
Tx_Idx++;
TWDR = data;
TWCR_ACK;
return;
 
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;
}
}
 
 
/tags/V0.23a/timer0.c
New file
0,0 → 1,170
/*#######################################################################################
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 / NON-COMMERCIAL USE ONLY
// + www.MikroKopter.com
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Die Portierung oder Nutzung 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 Portierung oder Nutzung der Software (oder Teile davon) auf andere Systeme (ausser der Hardware von www.mikrokopter.de) ist nur
// + mit unserer Zustimmung zulässig
/// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + 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 the sources to other systems or using the software on other systems (except 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 <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include "main.h"
 
volatile uint16_t CountMilliseconds = 0;
volatile uint16_t I2C_Timeout = 0;
 
 
/*****************************************************/
/* Initialize Timer 0 */
/*****************************************************/
void TIMER0_Init(void)
{
// set PB2 as output for the PWM used to signal compass heading
DDRB |= (1<<DDB2);
PORTB &= ~(1<<PORTB2);
 
 
// 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);
 
}
 
 
// -----------------------------------------------------------------------
ISR(TIMER0_OVF_vect)
{
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--;
}
}
 
 
// -----------------------------------------------------------------------
uint16_t SetDelay (uint16_t t)
{
return(CountMilliseconds + t - 1);
}
 
// -----------------------------------------------------------------------
int8_t CheckDelay(uint16_t t)
{
return(((t - CountMilliseconds) & 0x8000) >> 8); // check sign bit
}
 
// -----------------------------------------------------------------------
void Delay_ms(uint16_t wait)
{
uint16_t t_stop;
t_stop = SetDelay(wait);
while (!CheckDelay(t_stop));
}
 
/tags/V0.23a/analog.c
New file
0,0 → 1,120
/*#######################################################################################
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 / NON-COMMERCIAL USE ONLY
// + www.MikroKopter.com
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Die Portierung oder Nutzung 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 Portierung oder Nutzung der Software (oder Teile davon) auf andere Systeme (ausser der Hardware von www.mikrokopter.de) ist nur
// + mit unserer Zustimmung zulässig
/// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + 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 the sources to other systems or using the software on other systems (except 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 <util/delay.h>
#include "analog.h"
 
uint8_t AccPresent = 0;
 
void ADC_Init(void)
{
// 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));
}
 
 
uint16_t ADC_GetValue(ADChannel_t channel)
{
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);
}
 
 
 
/tags/V0.23a/Hex-Files/BootLoader_MEGA168_8MHZ_V0.2.hex
New file
0,0 → 1,61
:1038000011241FBECFEFD4E0DEBFCDBF11E0A0E09A
:10381000B1E0EEEAFBE302C005900D92A030B107E3
:10382000D9F711E0A0E0B1E001C01D92A238B107C4
:10383000E1F70C943B1C0C941D1C0895982F80916B
:10384000C00085FFFCCF9093C60008958091C00012
:103850008823E4F78091C600992708958DE40E949B
:103860001E1C8BE40E941E1C82E40E941E1C8CE421
:103870000E941E1C0895CFEFD4E0DEBFCDBFE0E074
:10388000F0E004917F01992494BE98E10FB6F8947A
:1038900090936000109260000FBE9092C50080E18E
:1038A0008093C4008091C00082608093C000909398
:1038B000C10086E08093C200EF01192D8091C00005
:1038C00087FF0DC0113031F48091C6008A3A89F12A
:1038D00010E005C08091C6008B3109F411E0CE01E3
:1038E00021968436910500F10F3F41F0002331F01D
:1038F000E0910001F0910101099516C08AE00E9453
:103900001E1C8DE00E941E1C86E50E941E1C80E38A
:103910000E941E1C8EE20E941E1C82E30E941E1C3E
:103920008AE30E941E1C05C080E29EE40197F1F725
:10393000C5CF0E942E1C0E94261C813611F489E5F9
:1039400033C1813471F40E94261CE82EFF24FE2C22
:10395000EE240E94261C9927E82AF92AF694E79477
:10396000F1C0823641F489E50E941E1C80E00E946D
:103970001E1C80E819C1823409F075C00E94261C03
:103980000E94261CD82E0E94261C082FB2E0AB2EC7
:10399000B1E0BB2E10E0E5010894A11CB11C1D157F
:1039A00018F40E94261C01C08FEF88831F5F17FF49
:1039B000F2CF38E7931609F0D4C0063409F03DC0C1
:1039C0008FEFE81687E3F80608F033C0CD2DA70186
:1039D00066277727440F551F661F771F6A017B01F3
:1039E000A2E0B1E011E08D9199272D913327322F7C
:1039F0002227822B932B0C01FA0110935700E89594
:103A000011244E5F5F4F6F4F7F4FC25061F785E0CB
:103A1000F60180935700E89507B600FCFDCF81E1E1
:103A200080935700E89576956795579547957A0165
:103A300089C080E00E941E1C85C0053409F082C048
:103A4000F7012D2DA2E0B1E0E1BD8F2F992782BDB6
:103A50008D9180BD3196FA9AF99AF999FECF21504D
:103A600099F77F016FC0873609F03DC00E94261C80
:103A70000E94261CC82F0E94261C863419F5C701F7
:103A8000AA27BB276C017D01CC0CDD1CEE1CFF1CA2
:103A9000F60105911491802F0E941E1C812F9927F9
:103AA0000E941E1C82E090E0A0E0B0E0C80ED91E8B
:103AB000EA1EFB1EC25061F7F694E794D794C794B0
:103AC000760139CF853409F036CFE1BC8F2D9927A7
:103AD00082BDF89A0894E11CF11C80B50E941E1C5E
:103AE000C15099F728CF853601F598E7991651F519
:103AF00080E090E0A0E0B0E023E0FC0120935700DC
:103B0000E89507B600FCFDCF80589F4FAF4FBF4FE1
:103B10008F3F37E3930730E0A30730E0B30768F344
:103B200081E180935700E8950DC0853469F488E100
:103B300090E02CE00FB6F894A895809360000FBE3B
:103B4000209360008DE030C08035E1F38C34D1F3F8
:103B5000803711F483E528C0843729F488E70E9470
:103B60001E1C80E021C0843521F40E94261C982E62
:103B7000E9CF8B3109F4DDCE8A3A09F4DACE863505
:103B800029F480E30E941E1C82E30EC0833741F4B7
:103B900086E00E941E1C84E90E941E1C8EE104C067
:0E3BA0008B3109F4C8CE8FE30E941E1CC4CEE8
:0400000300003800C1
:00000001FF
/tags/V0.23a/Hex-Files/MK3Mag_MEGA168_V0_23a_SVN72.hex
New file
0,0 → 1,856
:100000000C94FA010C9415020C9415020C94150230
:100010000C9415020C9415020C9415020C94150204
:100020000C9415020C9415020C9415020C941502F4
:100030000C9415020C9415020C9415020C941502E4
:100040000C94410F0C9415020C94A50A0C94150203
:100050000C946C0A0C9415020C9415020C94150265
:100060000C944A100C94150207BAA57A2C3BDA902E
:10007000C5BC8BFC663CFD10F8BD4D83923DB63A85
:100080009EBE5BBFCA3FC90FDA000829573F9F2DAC
:1000900049CBA5310F76C73493F27E37D00D013AA4
:1000A000B60B613D2AAAAB3F0000003F8000000074
:1000B000083B3BD74ABC846E023D2FC1FEBD9A313E
:1000C000743DDA3D83BE117FC73E4CBBE5BEAAAA94
:1000D0006C3F800000004D61676E657420582020E1
:1000E0002020202020204D61676E6574205920203B
:1000F0002020202020204D61676E6574205A20202A
:100100002020202020205261774D61676E65742089
:100110005820202020205261774D61676E65742041
:100120005920202020205261774D61676E65742030
:100130005A20202020204174746974756465204E13
:1001400069636B2020204174746974756465205262
:100150006F6C6C2020204D61676E65742058204FB5
:100160006666736574204D61676E65742058205211
:10017000616E676520204D61676E65742059204F60
:100180006666736574204D61676E657420592052F0
:10019000616E676520204D61676E6574205A204F3F
:1001A0006666736574204D61676E6574205A2052CF
:1001B000616E6765202043616C73746174652020F3
:1001C00020202020202048656164696E672020205F
:1001D000202020202020202020202020202020201F
:1001E000202020202020202020202020202020200F
:1001F0002020202020204163632058202020202020
:10020000202020202020416363205920202020200E
:10021000202020202020416363205A2020202020FD
:100220002020202020205261774163632058202025
:100230002020202020205261774163632059202014
:10024000202020202020526177416363205A202003
:1002500020202020202053657269616C20506F742B
:1002600069312020202053657269616C20506F74C1
:1002700069322020202053657269616C20506F74B0
:1002800069332020202048656164696E672058200A
:1002900020202020202048656164696E6720592055
:1002A00020202020202041747469747564652053D7
:1002B0006F7572636520493243204572726F7220F8
:1002C000202020202020493243204F6B61792020BC
:1002D00020202020202021212120494E434F4D5015
:1002E000415449424C4520212121005B25695D0094
:1002F0005B25695D002B2B2020204D4B334D414762
:100300002020202B2B200020562025642E2564251C
:1003100063002041434320537570706F7274202036
:100320000020202020202020202020202020002805
:10033000632920427573732C204275736B6572209C
:100340002020004D61676E65742053656E736F7277
:10035000733A2000583A252B3464202020417474CD
:10036000697475646500593A252B34642020206235
:1003700079005A3A252B3464200049324300554114
:10038000525400414343003F3F3F0043616C696268
:10039000726174696E673A2000537465703A202563
:1003A00031642000202D2D200020706175736520A0
:1003B000006D65617375726520686F72697A6F6E22
:1003C00074616C006D656173757265207665727419
:1003D0006963616C0073746F72652064617461009D
:1003E0002873746172742900284553432928737453
:1003F0006570290011241FBECFEFD4E0DEBFCDBF52
:1004000011E0A0E0B1E0ECE7F4E302C005900D924A
:10041000A43EB107D9F713E0A4EEB1E001C01D92EC
:10042000A838B107E1F70C943E080C9400000F9334
:100430001F93CF93DF93409170025091710280918E
:10044000510290915202481B590B509379024093EC
:100450007802C0915502D091560280914F0290913E
:100460005002C81BD90BD0935402C0935302009181
:100470007402109175028091760290917702081BA8
:10048000190B10937302009372022091570230915E
:1004900058022115310509F46CC0809159029091E0
:1004A0005A02481B590BCA01AA2797FDA095BA2FDB
:1004B0005AE0880F991FAA1FBB1F5A95D1F74427EE
:1004C00037FD4095542FBC01CD010E94051A309391
:1004D00007022093060220915B0230915C022115F5
:1004E000310509F452C080915D0290915E02C81BF3
:1004F000D90BCE01AA2797FDA095BA2F4AE0880F05
:10050000991FAA1FBB1F4A95D1F7442737FD409575
:10051000542FBC01CD010E94051A3093050220938F
:1005200004028091610290916202081B190BC801BC
:10053000AA2797FDA095BA2F2AE0880F991FAA1F16
:10054000BB1F2A95D1F720915F02309160024427AA
:1005500037FD4095542FBC01CD010E94051A309300
:1005600003022093020280910501823009F0D7C076
:1005700019C0309307022093060220915B0230914C
:100580005C022115310509F0AECF309305022093AE
:10059000040230930302209302028091050182300D
:1005A00009F0BDC0C0910002D091010280916502A6
:1005B00090916602C81BD90BD093FB01C093FA013E
:1005C0004091FE015091FF018091690290916A0271
:1005D000481B590B5093F9014093F80180916D022B
:1005E00090916E022091FC013091FD01821B930BD2
:1005F0009093F7018093F60149385105A4F48FEFE9
:100600004837580704F580EE9CEF9093F5018093EE
:10061000F401C938D10584F080E293E09093F301AE
:100620008093F2017CC080E293E09093F501809387
:10063000F401C938D10584F78FEFC837D807CCF556
:1006400080EE9CEFEBCFCA01AA2797FDA095BA2FA9
:10065000BC01CD010E940218DC01CB0120E030E09A
:100660004AE053E4BC01CD010E949F17DC01CB019D
:10067000BC01CD010E942C17DC01CB0120E030E051
:1006800041EE54E4BC01CD010E94EE18DC01CB0127
:100690002BED3FE049E450E4BC01CD010E949F17DF
:1006A000DC01CB01BC01CD010E94E517DC01CB01CF
:1006B000ACCFCE01AA2797FDA095BA2FBC01CD01E2
:1006C0000E940218DC01CB0120E030E04AE053E454
:1006D000BC01CD010E949F17DC01CB01BC01CD0103
:1006E0000E942C17DC01CB0120E030E041EE54E405
:1006F000BC01CD010E94EE18DC01CB012BED3FE0E7
:1007000049E450E4BC01CD010E949F17DC01CB01FC
:10071000BC01CD010E94E517DC01CB017FCFDF9149
:10072000CF911F910F9108952F923F924F925F9218
:100730006F927F928F929F92AF92BF92CF92DF92F1
:10074000EF92FF920F931F93CF93DF93CDB7DEB756
:1007500024970FB6F894DEBF0FBECDBF0F2EF0E08A
:100760002F2EF0E03F2EF0E04F2EF0E05F2EF02D28
:100770008201710129823A824B825C828091080257
:10078000909109020E94A80F882389F080916F023E
:10079000813009F456C18BB190E889278BB986E97D
:1007A00090E00E949F0F909309028093080280912D
:1007B0006F028130A9F02FEF3FEFF894C9018859FB
:1007C0009E4F815D924028F43093030120930201F3
:1007D00060C18FEF9FEF909303018093020159C195
:1007E000809104019927009709F005C180910602C4
:1007F00090910702AA2797FDA095BA2FBC01CD01C1
:100800000E9402187B018C018091040290910502E4
:10081000AA2797FDA095BA2FBC01CD010E9402180E
:100820001B012C018091020290910302AA2797FDDF
:10083000A095BA2FBC01CD010E94021869837A836A
:100840008B839C838091050199278130910509F460
:10085000FAC0823091050CF40EC1029709F402C16E
:1008600088249924C401AA2797FDA095BA2FBC011A
:10087000CD010E940218DC01CB012BED3FE049E4E1
:1008800050E4BC01CD010E94EE18DC01CB0120E058
:1008900030E041EE54E4BC01CD010E949F175B01A2
:1008A0006C01C401AA2797FDA095BA2FBC01CD0108
:1008B0000E940218DC01CB012BED3FE049E450E43B
:1008C000BC01CD010E94EE18DC01CB0120E030E03C
:1008D00041EE54E4BC01CD010E949F173B014C0145
:1008E000C601B5010E949917DC01CB01A80197014F
:1008F000BC01CD010E94EE187B018C01C601B5013F
:100900000E943619DC01CB0129813A814B815C813F
:10091000BC01CD010E94EE18DC01CB019C01AD01B0
:10092000C801B7010E94E9165B016C01C401B30163
:100930000E949917DC01CB01A2019101BC01CD01FC
:100940000E94EE187B018C01C401B3010E9436198C
:10095000DC01CB0129813A814B815C81BC01CD0155
:100960000E94EE18DC01CB019C01AD01C801B7016A
:100970000E94EA167B018C01C601B5010E94E517B1
:10098000DC01CB019093F2028093F102C801B70120
:100990000E94E517DC01CB019093F4028093F302EF
:1009A000A6019501C801B7010E946617DC01CB01C1
:1009B00020E030E044E353E4BC01CD010E94EE1896
:1009C000DC01CB012BED3FE049E450E4BC01CD015B
:1009D0000E949F17DC01CB01BC01CD010E94E517ED
:1009E000DC01CB019C0197FD39C088E691E0821BB8
:1009F000930B9C01E2CE019709F024CF8091040271
:100A000090910502AA2797FDA095BA2FBC01CD01B0
:100A10000E9402187B018C018091060290910702CE
:100A2000AA2797FDA095BA2FBC01CD010E940218FC
:100A3000DC01CB011C012D0157FA509457F850945A
:100A4000F1CE5F9AACCEF8948091B1029091B2024F
:100A50008090B3029090B402789405CF30952195A0
:100A60003F4FABCE8091F4019091F5018090F2015F
:100A70009090F301F8CE892B09F0F2CEF894809192
:100A800078039091790380907A0390907B03789417
:100A9000EACE789424960FB6F894DEBF0FBECDBF91
:100AA000DF91CF911F910F91FF90EF90DF90CF904A
:100AB000BF90AF909F908F907F906F905F904F907E
:100AC0003F902F9008954091F001463008F44DC0BA
:100AD0001092F00140E080911802882309F083C051
:100AE0005F98842F99278330910509F479C0843069
:100AF00091050CF07AC08130910509F4E1C00297AC
:100B000009F063C1209178023091790280910B0243
:100B100090910C02281739070CF42FC180910D0217
:100B200090910E028217930724F430930E022093C3
:100B30000D02209153023091540280910F02909146
:100B400010022817390724F43093100220930F0263
:100B50008091110290911202821793070CF0FFC04E
:100B60003093120220931102FAC0442309F4B3CF48
:100B700080910802909109020E94A80F882309F031
:100B8000F2C04091F00180910A02481709F4A9CF00
:100B90005091170250FFEAC080911802882309F093
:100BA000EAC05F98252F33272F5F3F4F842F992767
:100BB000880F991F281739070CF4E6C01092170206
:100BC0008CED95E00E949F0F90930902809308029C
:100BD0004091F001842F99278330910509F087CF48
:100BE00010921802F2C05F9A7CCF8430910509F40C
:100BF0009CC0059709F0E9C080910A02481781F36B
:100C0000E7E5F2E020910D0230910E0280910B0297
:100C100090910C02D901A81BB90BB0935802A09374
:100C20005702820F931F97FDADC0959587959093BE
:100C30005A02809359022091110230911202809140
:100C40000F0290911002B901681B790B70935C023E
:100C500060935B02820F931F97FD9EC095958795C9
:100C600090935E0280935D022091150230911602EE
:100C70008091130290911402A901481B590B5093C3
:100C8000600240935F02820F931F97FD83C095958A
:100C900087959093620280936102A739B1053CF079
:100CA0006739710524F0473951050CF077C0A0E091
:100CB000B0E089E1182E0E94201A4091F00190CFF7
:100CC00020E137E230930C0220930B0280EF98ED85
:100CD00090930E0280930D023093100220930F0226
:100CE0009093120280931102309314022093130206
:100CF0009093160280931502809100029091010258
:100D000090936602809365028091FE019091FF01AD
:100D100090936A02809369028091FC019091FD0199
:100D200090936E0280936D025BCF2091720230919E
:100D3000730280911302909114022817390724F44A
:100D400030931402209313028091150290911602A1
:100D50008217930724F4309316022093150281E042
:100D60008093180232C04091F00112CF8091180296
:100D7000882309F016CF5F9A15CF30930C02209389
:100D80000B02CCCE019651CF5F5F5093170284E6E1
:100D900090E018CF01967BCF019660CF81E08093E1
:100DA0006F025F98A0E0B0E089E1182E0E94251A3A
:100DB00080ED97E00E949F0F9093090280930802B4
:100DC000109217024091F0010BCF40930A02089550
:100DD00080910602909107029093BC028093BB021F
:100DE00080910402909105029093BE028093BD020F
:100DF00080910202909103029093C0028093BF02FF
:100E000080917802909179029093C2028093C102FE
:100E100080915302909154029093C4028093C30234
:100E200080917202909173029093C6028093C502E2
:100E300020910501822F99278130910561F0823040
:100E400091051CF10297A1F08FEF9FEF9093C802DC
:100E50008093C70228C08091B1029091B202909312
:100E6000C8028093C7028091B3029091B4021BC064
:100E70008091F4019091F5019093C8028093C7028C
:100E80008091F2019091F3010EC0892BE9F68091D7
:100E90007803909179039093C8028093C702809160
:100EA0007A0390917B039093CA028093C902809148
:100EB000590290915A029093CC028093CB02809178
:100EC0005702909158029093CE028093CD02809168
:100ED0005D0290915E029093D0028093CF02809148
:100EE0005B0290915C029093D2028093D102809138
:100EF0006102909162029093D4028093D302809118
:100F00005F02909160029093D6028093D502809107
:100F1000F00199279093D8028093D7028091020123
:100F2000909103019093DA028093D9021092DC022F
:100F30001092DB021092DE021092DD028091FA0123
:100F40009091FB019093E0028093DF028091F80181
:100F50009091F9019093E2028093E1028091F60171
:100F60009091F7019093E4028093E3028091000254
:100F7000909101029093E6028093E5028091FE0138
:100F80009091FF019093E8028093E7028091FC0129
:100F90009091FD019093EA028093E9028091E4012F
:100FA000992787FD90959093EC028093EB028091B6
:100FB000E501992787FD90959093EE028093ED02CD
:100FC0008091E601992787FD90959093F002809398
:100FD000EF02822F99279093F6028093F5020895ED
:100FE00080913802882369F4109201021092000265
:100FF0001092FF011092FE011092FD011092FC016F
:10100000089582E00E94C00F2091000230910102F9
:10101000280F391F37FD29C03595279530930102D8
:101020002093000283E00E94C00F2091FE013091C6
:10103000FF01280F391F37FD1EC0359527953093C6
:10104000FF012093FE0186E00E94C00F2091FC0169
:101050003091FD01280F391F37FD0AC035952795BE
:101060003093FD012093FC0108952F5F3F4FD4CFB3
:101070002F5F3F4FF3CF2F5F3F4FDFCFCFEFD4E056
:10108000DEBFCDBF3E98469A0E94B2110E942B0F40
:101090000E949C090E94D50F0E941110789486E04E
:1010A00091E00E940F0F85E591E00E940F0F809163
:1010B0003802882309F02FC15F9A88EC90E00E94E3
:1010C0009F0F9093090280930802E7E5F2E0A0E009
:1010D000B0E089E1182E0E94201A1092F1011092BE
:1010E000B702109275031092F00180E090E00E9428
:1010F0009F0F90931B0280931A0280911902C82FB0
:10110000DD27C130D10531F1C230D1050CF45BC00F
:10111000C230D10509F472C0239709F486C080E07B
:1011200090E00E949F0F90931B0280931A021092EE
:1011300019020E94BB0C8091200290912102892B00
:10114000E9F50E94600A80911902C82FDD27C1309D
:10115000D105D1F680911A0290911B020E94A80F2E
:10116000882339F380E00E94C00F9093710280932E
:10117000700281E00E94C00F909581959F4F9093DF
:1011800075028093740287E00E94C00F909356020C
:10119000809355020E94F007CE010E949F0F90930A
:1011A0001B0280931A0282E0809319020E94BB0CFA
:1011B0008091200290912102892B19F20E94580AF5
:1011C0000E94920D9ACFCD2B09F0A9CF80911A02DF
:1011D00090911B020E94A80F882309F4AACF8BB11B
:1011E0008F798BB982E090E00E949F0F90931B0251
:1011F00080931A0281E080931902D8CF80911A025D
:1012000090911B020E94A80F882309F492CF8BB102
:1012100080668BB9CE010E949F0F90931B02809332
:101220001A0283E080931902C1CF80911A02909133
:101230001B020E94A80F882309F47BCF80E00E9444
:10124000C00F909352028093510281E00E94C00F20
:10125000909581959F4F909377028093760287E0D7
:101260000E94C00F9093500280934F020E94F0079B
:1012700081E090E00E949F0F90931B0280931A02DE
:10128000109219020E9417028091F101882331F413
:1012900080917503882311F48091B7028093F00147
:1012A0008091F001882391F10E94630540913902F9
:1012B000442319F041504093390220911E0230918D
:1012C0001F022115310531F02150304030931F02AB
:1012D00020931E028091200290912102009729F014
:1012E00001979093210280932002232B09F021CFB4
:1012F000442309F01ECF80913802882351F082E008
:101300008093050181E08093040113CF0E94940330
:10131000CDCF83E0F5CF8FE791E00E940F0FCCCEC9
:10132000982F8091C10083FF06C08091C00085FF87
:10133000FCCF9093C6000895CF93CFB720E130E063
:10134000F8948091C1008F778093C1008091C10093
:101350008F7B8093C10050985898519A5998832F49
:1013600099278093C5002093C4008091C0008260BB
:101370008093C0008091C2008F778093C2008091DB
:10138000C2008F7B8093C2008091C2008F7D8093CA
:10139000C2008091C2008F7E8093C2008091C20003
:1013A000877F8093C2008091C1008B7F8093C100B2
:1013B0008091C20084608093C2008091C2008260EC
:1013C0008093C2008091C10080618093C1008091B0
:1013D000C10088608093C1008091C00087FF0CC06D
:1013E0008091C6008091C000882334F48091C600AB
:1013F0008091C0008823A4F38091C100806880930D
:10140000C1008091C10080648093C10080918F01F0
:10141000909190010E949F0F9093740380937303A7
:1014200080918D0190918E010E949F0F9093AE024A
:101430008093AD0210922B02109229021092280282
:101440001092270281E0809391011092980287E127
:101450008093990210929C028BE080939A021092E2
:101460009B028DE00E9490098AE00E94900983E42B
:101470000E94900980E50E9490098AE30E949009E9
:1014800086E50E94900980E30E9490098EE20E9406
:10149000900982E30E94900983E30E94900981E60B
:1014A0000E9490098AE00E949009CFBFCF910895D1
:1014B000519A59988091C10088608093C100089525
:1014C000809191018823E1F38091C100877F80930F
:1014D000C1005198599808951F920F920FB60F921C
:1014E00011248F939F93EF93FF9380919101882311
:1014F000A9F480912C0290912D020196FC01E550F7
:10150000FD4FE081ED3079F08837910561F09093DF
:101510002D0280932C02E093C6000EC010922D0283
:1015200010922C0209C010922D0210922C0281E020
:1015300080939101E093C600FF91EF919F918F916D
:101540000F900FBE0F901F9018951F920F920FB61D
:101550000F9211242F933F934F935F938F939F93F9
:10156000AF93BF93CF93DF93EF93FF935091C60058
:1015700080912B02882309F073C0409130024423EC
:10158000B9F45332E1F05D3011F1E42FFF27E65852
:10159000FD4F50834F5F4093300280912E02909117
:1015A0002F02850F911D90932F0280932E0258C019
:1015B0004E3148F38093300280932B0251C05093F8
:1015C0007A0281E08093300283E290E0ECCFA42F96
:1015D000BB27A658BD4FFD013297808120912E0276
:1015E00030912F02281B3109ED0121978881281B9A
:1015F0003109C9019F7090932F0280932E0200241D
:10160000880F991F001C880F991F001C892F902D8F
:10161000982F935C2F733070235C8081891729F099
:1016200010922B02109230021BC088818217C1F7E2
:101630005C934F5F40932A0281E080932B0280915C
:101640007C02823579F788E190E02CE00FB6F894BF
:10165000A895809360000FBE209360001092300226
:10166000FF91EF91DF91CF91BF91AF919F918F91BA
:101670005F914F913F912F910F900FBE0F901F9050
:101680001895AC01A0E0B0E09D01A817B90748F497
:10169000EBEFF2E08191280F311D1196A417B507E9
:1016A000C8F33F70FD01E550FD4FC9010024880FCC
:1016B000991F001C880F991F001C892F902D835C97
:1016C00080831196FD01E550FD4F2F733070822FFE
:1016D000835C8083A450BD4F8DE08C931092910168
:1016E0008091FB028093C6000895BF92CF92DF9253
:1016F000EF92FF920F931F93CF93DF93CDB7DEB797
:101700002C859D857E85BB2483E28093FB029F59B7
:101710009093FC022093FD0203E010E0772309F48C
:10172000ADC0CF84D88843E1E42EF12CEC0EFD1E31
:10173000A989BA897150109709F4A0C0109709F4CB
:101740003CC0F601EB0DF11DB3949081119789F423
:101750007723A1F1F70122E030E0E20EF31ED7017A
:10176000C080D180E20EF31E0D90BC91A02DBB2451
:101770007150109719F1F601EB0DF11DB3944081F2
:10178000119709F466C01097D1F0F601EB0DF11D29
:10179000B39460811197A1F4772391F0F701329609
:1017A000D701CD90DC9032E0E32EF12CEE0EFF1E3F
:1017B000A081B181BB24715003C090E040E060E0A3
:1017C000F801E550FD4F892F86958695835C8083CF
:1017D0000F5F1F4FF801E550FD4F892F9927837048
:1017E000907082959295907F9827807F98275527B3
:1017F0009A01329522952F7023273F702327822B41
:10180000835C80830F5F1F4FF801E550FD4F4F70E1
:101810005070440F551F440F551F862F99270024E1
:10182000880F991F001C880F991F001C892F902D6D
:10183000842B835C80830F5F1F4FF801E550FD4FC1
:101840006F73635C60830F5F1F4F109709F076CF53
:1018500015C0772309F4B3CFF701A2E0B0E0EA0E98
:10186000FB1ED701C080D18022E030E0E20EF31EE3
:101870000D90BC91A02DBB24715085CFC8010E9452
:10188000410BDF91CF911F910F91FF90EF90DF906F
:10189000CF90BF900895A3E07A2F40912A0246503E
:1018A00009F45FC0E72FFF27E658FD4F80818D5375
:1018B0007F5FE72FFF27E658FD4F20812D537F5F85
:1018C000E72FFF27E658FD4F30813D537F5FE72F1D
:1018D000FF27E658FD4F60816D537F5F9927880F82
:1018E000991F880F991F522F52955F70582B822F86
:1018F00099278F70907082959295907F9827807F1E
:101900009827232F26952695282B832F9927837098
:1019100090700024969587950794969587950794DF
:10192000982F802D682B41504F3FD9F0EA2FFF2789
:10193000E658FD4F5083AF5F41504F3F91F0EA2F83
:10194000FF27E658FD4F2083AF5F41504F3F49F0DE
:10195000EA2FFF27E658FD4F6083AF5F442309F06D
:10196000A1CF8DE792E09093290280932802A350A3
:10197000A0932702089580912B02882309F40895EB
:101980000E944B0C80917B02843609F446C0809102
:101990007C0299278436910559F1853691058CF49E
:1019A0008136910509F47FC08236910509F488C01B
:1019B00010922902109228021092270210922B02F4
:1019C00008958836910509F45AC0893691050CF0BE
:1019D0004CC08736910561F7809126028061809323
:1019E000260280ED97E09093210280932002E0CFC1
:1019F000E0912802F091290290818AE0989FC0012D
:101A000011249093900180938F01892B51F3809141
:101A10002602826080932602E4CF80917C0299277F
:101A20008B36910521F08737910509F0B0CFA09151
:101A30002802B091290288E0E1EBF2E00D900192DA
:101A40008A95E1F78091260288608093260281E0E2
:101A5000809305018091B802809304018FEF90E09C
:101A600090931F0280931E0292CF8637910509F052
:101A70009FCF80912602816080932602B2CFE091B1
:101A80002802F0912902808187FD35C082E0809391
:101A9000220210921D0210921C0280912602806286
:101AA000809326029ECFE0912802F0912902808146
:101AB000809325028091260284608093260291CF34
:101AC000A0912802B09129028BE0E2EAF2E00D90A9
:101AD00001928A95E1F78091A40281FF07C080916D
:101AE000B7028F5F8630D9F08093B7028091AB0246
:101AF0008093240276CF8081809590912302892B58
:101B00008093230291818AE0989FC00111249093D1
:101B10001D0280931C0284E080932202BECF1092AB
:101B2000B702E4CFCF93DF93CDB7DEB760970FB6A0
:101B3000F894DEBF0FBECDBF8091C10083FF66C1A8
:101B400080919101882309F461C12091260222FD30
:101B500039C080912402882309F06BC080918F01E5
:101B600090919001892B09F0C7C021FF7DC00E9490
:101B7000E80682E490E09F938F9389EB92E09F9335
:101B80008F9381E08F9383E08F9384E48F930E94FF
:101B9000750B80918F01909190010E949F0F9093FF
:101BA000740380937303809126028D7F80932602B5
:101BB0002DB73EB7295F3F4F0FB6F8943EBF0FBE1B
:101BC0002DBF24C180912502992782959295907FFF
:101BD0009827807F98278A529F4F40E150E0BC01B0
:101BE000CE0101960E94CF1680E190E09F938F93E3
:101BF000CE0101969F938F9381E090E09F938F9306
:101C000085E292E09F938F9382E08F9383E08F939E
:101C100081E48F930E94750B8FEF80932502809152
:101C200026028B7F809326022DB73EB7255F3F4F5C
:101C3000C3CF81E090E09F938F9384E292E09F93E3
:101C40008F9381E08F9383E08F9382E48F930E9440
:101C5000750B109224028DB79EB707960FB6F894B5
:101C60009EBF0FBE8DBFD2C080911C0290911D02FD
:101C7000892BB9F5822F992785FF4AC080912202CE
:101C8000843008F461C0809123020E94CB1110922D
:101C9000230280E590E09F938F9382E991E09F93E8
:101CA0008F9381E08F9383E08F9388E48F930E94DA
:101CB000750B8DB79EB707960FB6F8949EBF0FBEF3
:101CC0008DBF80911C0290911D020E949F0F9093E6
:101CD000B0028093AF02809126028F7D809326020E
:101CE00095C08091AF029091B0020E94A80F882306
:101CF00029F620912602BECF809173039091740340
:101D00000E94A80F882309F032CF209126022DCF00
:101D100084FD53C083FD67C080FF78C08AE090E0F7
:101D20009F938F9388E992E09F938F9381E08F93A5
:101D300083E08F9386E58F930E94750B8091260236
:101D40008E7F8093260287CF10924D0286ED92E01F
:101D50009F938F9385EB91E19F938F930E94201423
:101D600084E190E09F938F9382E991E09F938F931A
:101D700081E090E09F938F9382E292E09F938F9314
:101D800082E08F9383E08F9388E48F930E94750B9A
:101D900080912202982F9F5F2DB73EB7215F3F4F62
:101DA0000FB6F8943EBF0FBE2DBF843018F01092CE
:101DB000220287CF9093220284CF8BE090E09F9302
:101DC0008F9382EA92E09F938F9381E08F9383E0D9
:101DD0008F9387E48F930E94750B809126028F7EEC
:101DE0008093260238CF82E090E09F938F9382E029
:101DF00091E09F938F9381E08F938F938BE48F93E8
:101E00000E94750B80912602877FD0CE60960FB618
:101E1000F894DEBF0FBECDBFDF91CF9108951F9321
:101E2000CF93DF93EC0110E08881882381F0A0E05C
:101E3000B0E0AC0FBD1F1F5F8C910E949009A12FD5
:101E4000BB27FE01EA0FFB1F8081882391F7DF91FA
:101E5000CF911F910895229A2A9884B58C7084BDE1
:101E600085B5837385BD82E085BD16BC80916E000B
:101E7000897F80936E0080916E00816080936E00F8
:101E800008951F920F920FB60F9211242F933F9334
:101E90004F938F939F9386B5855686BD20910201FF
:101EA0003091030137FD3FC0809136029091370297
:101EB000019641E08C37940728F12A9A1092370254
:101EC0001092360280913502815051F58AE080935C
:101ED000350280913302909134020196909334023E
:101EE000809333028091310290913202892BE9F084
:101EF0008091310290913202019790933202809347
:101F0000310213C09093370280933602265F3F4F11
:101F100082179307B8F22A98809135028150B1F266
:101F20008093350202C02A98C9CF9F918F914F911B
:101F30003F912F910F900FBE0F901F9018952091F9
:101F4000330230913402280F391FC90101970895D7
:101F50002091330230913402821B930B892F990F09
:101F6000990B80780895CF93DF930E949F0FEC0127
:101F7000CE010E94A80F8823D9F3DF91CF91089555
:101F800080937C0080917A00806180937A008091B8
:101F90007A00806480937A0080917A0084FFFCCF7D
:101FA0008091780090917900089587B1807F87B9FA
:101FB00088B1807F88B98AB180668AB98BB18F7900
:101FC0008BB910927C0080917A00877980937A0097
:101FD00080917A00876980937A0010927C008091CA
:101FE0007A00806480937A0088B18C6088B980E23E
:101FF0009EE40197F1F782E00E94C00F895E934052
:1020000020F481E08093380208C083E00E94C00F72
:10201000895E9340B0F31092380288B1837F88B90B
:1020200008959FB7F89484B18F7C84B985B180639B
:1020300085B987B18F7C87B988B18F7C88B91092B8
:102040003D0210923C0210923E0210923B0210920E
:102050003A0210923F028FED8093BC008091BC0049
:1020600085648093BC0080E58093BA008091BC00B9
:10207000856D8093BC0010927E0387E180937F037F
:102080001092800383E08093810385EC8093BC00F1
:102090009FBF08951F920F920FB60F9211242F9396
:1020A0003F938F939F93AF93BF93EF93FF93809151
:1020B000B9009927887F907080389105A9F0813800
:1020C00091054CF0883A910509F444C0883B91058C
:1020D00061F185EC38C10097D9F080369105C9F7D8
:1020E0008FEF80934202F5CF3091BB0020914202E6
:1020F0002F3F09F44CC080913F02281758F080917F
:102100003F02281709F488C02F5F20934202E1CFD5
:1021100085ED19C1E22FFF27ED5BFD4F30838091E4
:102120004002830F80934002EFCFE0913C02F09198
:102130003D02309709F04CC09091410280913E02DF
:10214000981709F4A2C030E09F5F9093410230934A
:10215000BB00BFCF1092410210924002E0913C02BE
:10216000F0913D02309729F080913E02823008F0D4
:1021700051C030E080914002830F809340028091F3
:1021800041028F5F809341023093BB00A2CF832F27
:1021900099278230910509F450C08330910544F1AC
:1021A0008330910509F49EC0049709F4BCC01092D5
:1021B0003B0210923A0210923F0210923D0210929E
:1021C0003C0210923E02109242023093400281CFB4
:1021D0009091410280913E02981708F0AFCFE90F2D
:1021E000F11D308180914002830F80934002ACCF7B
:1021F0000197E9F68EE793E090933D0280933C02CD
:1022000084E080933E0210923B0210923A021092B8
:102210003F02D9CF3081AECF80914002809580932C
:1022200040028317B1F18091F7029091F802019674
:102230009093F8028093F70267CF82E893E090933F
:102240003D0280933C0286E080933E0210923B0266
:1022500010923A0210923F0280910602909107027A
:1022600090938303809382038091040290910502EE
:1022700090938503809384038091020290910302DE
:1022800090938703809386039ECF309140023095D0
:102290005BCFA0913A02B0913B021097C9F030E0B9
:1022A00080913F02381728F013C0A0913A02B091F4
:1022B0003B02E32FFF27AE0FBF1FED5BFD4F808179
:1022C0008C933F5F80913F02381778F32091420250
:1022D0008091F9029091FA0201969093FA0280930C
:1022E000F90212CF8CE793E090933D0280933C0279
:1022F00082E080933E0288E793E090933B028093D4
:102300003A0284E080933F028091020190910301A0
:1023100090937D0380937C03109205011092040139
:102320002093390250CF85E793E090933D0280934C
:102330003C0223E020933E0290933B0280933A02BA
:1023400020933F0240CF8093BC00FF91EF91BF915B
:10235000AF919F918F913F912F910F900FBE0F9052
:102360001F901895579A5F98089590914D02903557
:1023700040F4E92FFF27EE56FE4F80839F5F909336
:102380004D02089590E2E2E9F1E08FE491938150EB
:1023900087FFFCCF0895EF92FF920F931F93CF9387
:1023A000DF93082F112700FF08C080914E02882379
:1023B00009F459C0815080934E0201FF0AC09091E8
:1023C0004E028091E201981709F455C09F5F9093E7
:1023D0004E0200FF02C001FD4BC00E94C21190914D
:1023E0004E028091E201891718F480934E02982FD3
:1023F0009A3078F581E180934D02892F99279F9338
:102400008F938BEE92E09F938F9385EBE82E81E183
:10241000F82EFF92EF920E9420148DB79EB7069679
:102420000FB6F8949EBF0FBE8DBF90914E02C92F7C
:10243000DD27C130D10509F46AC0C230D105F4F0FE
:10244000229709F4DDC091509093E20110924E0260
:102450008CC180E180934D02892F99279F938F93A0
:1024600080EF92E0D0CF8091E20180934E02A5CF21
:1024700010924E02B2CF10924E02ABCF209719F7B6
:1024800010924D0285EF92E09F938F93FF92EF920F
:102490000E94201484E180934D020F900F900F90C2
:1024A0000F9081E690E09F938F9387E190E09F9358
:1024B0008F93DF93CF9387E093E09F938F93FF9267
:1024C000EF920E9420148DB79EB70A960FB6F8942B
:1024D0009EBF0FBE8DBF80913802882309F00AC1CC
:1024E00088E280934D0281E293E09F938F9385EB86
:1024F00091E19F938F930E9420140F900F900F9063
:102500000F908CE380934D028FE293E06EC01092A7
:102510004D0283E493E09F938F93C5EBD1E1FF924B
:10252000EF920E94201484E180934D020F900F904F
:102530000F900F9080910602909107029F938F93C6
:1025400084E593E09F938F93FF92EF920E94201473
:1025500088E280934D028DB79EB706960FB6F89429
:102560009EBF0FBE8DBF80910402909105029F9384
:102570008F9386E693E09F938F93FF92EF920E9452
:1025800020148CE380934D028DB79EB706960FB64C
:10259000F8949EBF0FBE8DBF8091020290910302FE
:1025A0009F938F9382E793E09F938F93FF92EF9295
:1025B0000E9420148DB79EB706960FB6F8949EBF62
:1025C0000FBE8DBF8091050199278130910509F4D7
:1025D000B4C0823091050CF4A3C0029709F4B3C0D3
:1025E00084E380934D0287E893E09F938F93FF925B
:1025F000EF920E9420140F900F900F900F90B5C093
:1026000010924D028BE893E09F938F93C5EBD1E13D
:10261000FF92EF920E94201484E180934D020F906C
:102620000F900F900F908091F00199279F938F93B7
:1026300089E993E09F938F93FF92EF920E94201479
:102640008DB79EB706960FB6F8949EBF0FBE8DBF8E
:102650008091F00199278330910509F45BC08430A3
:102660009105CCF18430910509F473C0059709F404
:1026700076C088E280934D0284EA93E09F938F9323
:10268000FF92EF920E9420140F900F900F900F90E6
:102690008091F0018823C1F589E480934D0280EE9A
:1026A00093E09F938F93FF92EF920E9420140F90DC
:1026B0000F900F900F9003FF05C08091F1018F5F85
:1026C0008093F1018091F001853010F402FF4DC03C
:1026D0001092F1014AC081309105E1F0029749F66C
:1026E00088E280934D0281EB93E09F938F93DF9379
:1026F000CF93C8CF88E280934D0282E193E09F930D
:102700008F93FF92EF92F7CE85E480934D0288EE8F
:1027100093E0C7CF88E280934D0289EA93E0AECF81
:10272000892B09F05DCF84E380934D028AE793E023
:102730009F938F93DF93CF935CCF84E380934D027D
:102740008EE793E0F5CF84E380934D0283E893E036
:10275000EFCF88E280934D0284EC93E0C6CF88E20D
:1027600080934D0285ED93E0C0CFDF91CF911F9113
:102770000F91FF90EF900895EF92FF920F931F93A8
:10278000CF93DF937C018B01EA01452B71F0F801B7
:1027900081918F01F7010995219739F0F801819115
:1027A0008F01F7010995219791F7DF91CF911F9143
:1027B0000F91FF90EF900895EF92FF920F931F9368
:1027C000CF93DF937C018B01EA01452B81F0F80167
:1027D0000F5F1F4F8491F7010995219741F0F80190
:1027E0000F5F1F4F8491F7010995219781F7DF91C2
:1027F000CF911F910F91FF90EF9008950F931F932A
:10280000CF938C01C62F161634F480E2F801099597
:10281000C1501C16D4F3CF911F910F9108950F93BF
:102820001F93CF938C01C62F161634F480E3F80162
:102830000995C1501C16D4F3CF911F910F910895A3
:102840002F923F924F925F926F927F928F929F92C0
:10285000AF92BF92CF92DF92EF92FF920F931F93AE
:10286000CF93DF93CDB7DEB7E0970FB6F894DEBF16
:102870000FBECDBF88249924540149E4C42ED12C25
:10288000CC0EDD1E2996EEACFFAC2997B701F701FF
:102890001491112331F0153221F00894E11CF11C40
:1028A000F6CFA701461B570B09F095C0112309F479
:1028B0005DC20894E11CF11C1FA63FA4232C0FEF5E
:1028C00039A6F7010894E11CF11C14911537C9F1E0
:1028D000812F80628837A9F1103209F440C0133289
:1028E00009F491C01A3209F47DC01D3209F47AC08E
:1028F0001B32C9F11E32C9F1103309F48EC0812F89
:102900008153893008F082C040E050E0CA01880F4E
:10291000991F880F991F880F991F840F951F480FC3
:10292000591F410F511D40535040F7010894E11CBD
:10293000F11C1491812F80538A3040F3242E1537D7
:1029400039F630FE3DC0F60184E090E0C80ED91E95
:1029500080809180A280B380103209F0C0CF89A519
:10296000882309F0AECF19A7ACCFF7010894E11C7A
:10297000F11C14911A3209F455C040E050E014C023
:10298000CA01880F991F880F991F880F991F840FFC
:10299000951F480F591F410F511D40535040F701DB
:1029A0000894E11CF11C1491812F80538A3040F36C
:1029B000EFEF4F3F5E0714F44FEF5FEF042F86CF2A
:1029C000F60182E090E0C80ED91E808191814C0111
:1029D000AA24BB2481CF27968EAD9FAD27970E9456
:1029E000DC1364CF1A3251F4F60182E090E0C80E95
:1029F000D91E208022200CF064CF219490E1392A46
:102A0000EFED3E225ECF98E0392A5BCF1836C9F051
:102A10001C36D1F481E0382A54CF34FC52CFF0E296
:102A20003F2A4FCFF60182E090E0C80ED91E4081C8
:102A300051819FEF4F3F590714F44FEF5FEF042F81
:102A400040CF24E0322A3DCF133609F459C1143463
:102A500009F42BC1143609F428C1193609F425C12B
:102A60001F3409F41BC11F3609F418C1103709F4CB
:102A700005C1133709F4BEC0153509F4F8C0153780
:102A800009F4F5C0183509F450C0183709F44DC0E1
:102A9000112309F46BC1CE0101969DA78CA7198360
:102AA00081E0482E19A6632C7724042D5FA45418C6
:102AB00057FC39C029A5222391F10F5F050DC301F1
:102AC00080739070892B09F446C1222309F03DC11F
:102AD00066FC2CC1C30180739070809709F41CC1FF
:102AE000652D27968EAD9FAD27970E940F14842DDC
:102AF000992787FD9095AC016CA57DA527968EAD95
:102B00009FAD27970E94BC1364FEC0CE201A622D91
:102B100027968EAD9FAD27970E94FE13B7CE66FE17
:102B2000CDCF0E5FCBCF5524C5CFE0E1EEA733FE6E
:102B300007C081149104A104B10411F0F0E43F2A0C
:102B400019A60FA707FD02C02FED3222CE018996EC
:102B50009DA78CA781149104A104B10419F49FA529
:102B6000992361F1EEA54E2E55246624772418AAE8
:102B700084149504A604B70410F0F1E0F8ABC50185
:102B8000B401A30192010E94E319DC01CB01082FDB
:102B90008A30F0F4005DECA5FDA50293FDA7ECA73B
:102BA000C501B401A30192010E94E31949015A0130
:102BB000F8A9FF23E1F62EA5283079F0632C7724BD
:102BC000CE010196482EFCA54F1A28E2420E6DCF89
:102BD000095A183501F70F7DDECF632C772463FE89
:102BE000EFCF003369F380E3ECA5FDA58293FDA749
:102BF000ECA7E6CFF60182E090E0C80ED91E019066
:102C0000F081E02DFDA7ECA7EF2B81F4FE013196BA
:102C1000FDA7ECA788E289838EE6818385E78B8315
:102C20008CE68C838D8389E28E831F8207FD15C01D
:102C3000802F992787FD9095AC0160E070E08CA50E
:102C40009DA50E94DC16009731F0482EFCA54F1A76
:102C500004150CF027CF402E25CFECA5FDA5019043
:102C60000020E9F731974E2E2CA5421A1BCF1535BF
:102C700011F481E0382A9AE09EA762CFF60182E043
:102C800090E0C80ED91E808191814C01AA24BB24FA
:102C900090E19EA7E0E43E2A18E752CF1F3411F4DA
:102CA000E1E03E2AF8E0FEA74BCF143411F491E0A6
:102CB000392A30FE18C0F60184E090E0C80ED91E13
:102CC00080809180A280B380B7FE0AC0B094A094A7
:102CD00090948094811C911CA11CB11C8DE289A749
:102CE0009AE09EA72ECFF60182E090E0C80ED91E92
:102CF000808191814C01AA2497FCA094BA2CE4CF46
:102D0000FE013196FDA7ECA7F60182E090E0C80E27
:102D1000D91E80818983C4CE822D801B682F27967F
:102D20008EAD9FAD27970E940F14DACE80E38AA75D
:102D30001BA742E050E0BE01665D7F4F27968EAD37
:102D40009FAD27970E94BC13C5CE41E050E0BE0165
:102D5000675D7F4FF3CF822D801B682F27968EAD46
:102D60009FAD27970E94FE1329A5AFCEE0960FB620
:102D7000F894DEBF0FBECDBFDF91CF911F910F91B1
:102D8000FF90EF90DF90CF90BF90AF909F908F908B
:102D90007F906F905F904F903F902F900895FB0130
:102DA000DC0140FF05C002C005900D9205900D9218
:102DB00042505040C8F70895FC014150504030F057
:102DC00001900616D1F73197CF01089588279927EA
:102DD00008955058192EA4D101D054C1BA176207D2
:102DE000730784079507B1F188F40EF410940B2E45
:102DF000BA2FA02D062E622F202D072E732F302DD7
:102E0000082E842F402D092E952F502DFF27552356
:102E1000B9F0591B49F0573E98F0469537952795DC
:102E2000A795F0405395C9F776F0BA0F621F731F4C
:102E3000841F30F4879577956795B795F040939503
:102E400017FA0F2E0895BF1BBB27BA0B620B730B2B
:102E5000840BF6CFDEF690C1AA2797FDA160AF9351
:102E60009F775FE340E8613071058407950720F0A4
:102E70000E945A18AF9108959F938F937F936F93F9
:102E8000E8E6F0E00E945D182F913F914F915F912D
:102E90009F938F937F936F939FE380E877276627B5
:102EA00050680E94EA160E9449192F913F914F9154
:102EB0005F910E94EE185FE349EC3FE02BED9068D4
:102EC0000E94EA16AF91A0FD90680895552319F06D
:102ED000992351F018C09923A1F097FB6BED7FE087
:102EE00089EC9FE397F90895552359F02AF46BED87
:102EF0007FE089E490E4089566277727882799275B
:102F000008950C945A181F93112797FD116057FDCF
:102F100012600E949F170E948B1911FF08C02BEDB1
:102F20003FE049E450E410FD50680E94EA161F910A
:102F3000089550E449EC3FE02BED6ED080C0F0D016
:102F400001D0A0C0552359F0992369F09F575F57CE
:102F5000951B33F442F4903811F4915805C0AAC07F
:102F600091589F3F09F408C1BB27112462177307CA
:102F7000840730F4660F771F881FBB1F915098F3AA
:102F800011D00F920FD00F920DD0A0E8261737075F
:102F900048071B0609F0A048BA2F602D7F918F913A
:102FA00000240895A0E80024621773078407B10580
:102FB00028F0621B730B840BB1090A2A660F771F76
:102FC000881FBB1FA69581F7089597FBB5D09F3743
:102FD00038F0FEE9F91B982F872F762F6B2F05C04D
:102FE000C8C09695879577956795F150D0F73EF4D0
:102FF00090958095709561957F4F8F4F9F4F089565
:10300000E89403C097FB0EF4F3DFB62F672F782FF9
:10301000892F9EE9002436C05F77552319F4442395
:103020000AF048C02F933F934F935F9388DF552753
:103030004427A4D05F914F913F912F91CFC01F9310
:103040009F7750EC49E43FE02BEDC4DE10E89F771A
:103050005FE349EC3FE02BED6217730784079507A8
:1030600020F050EC49E4B6DE112751D19068EAE82F
:10307000F0E023D091271F9108959A95BB0F661F0A
:10308000771F881F11249923A1F08823B2F79F3F4F
:1030900059F0BB0F48F421F4002011F460FF04C084
:1030A0006F5F7F4F8F4F9F4F881F9795879597F939
:1030B00008955FC09FEF80EC0895FF92EF92DF923A
:1030C000CF92BF926B017C01B59016D0B590BB201A
:1030D00069F09F938F937F936F93B601C7010CD0D4
:1030E0002F913F914F915F910E949F17BF90CF907A
:1030F000DF90EF90FF9008953DD102C09601A701A7
:10310000EF93FF930E94EE18FF91EF9133D1EF936D
:10311000FF930E94EA16FF91EF91BA9479F7089510
:10312000052E092607FA440F551F5F3F79F0AA279D
:10313000A51708F051E04795880F991F9F3F31F080
:10314000BB27B91708F091E0879508959F919F914B
:103150001124B0CF97FB880F991F9F3F31F0BB27F9
:10316000B91708F091E0879508959F919F911124D8
:10317000A1CF66277727882799270895EBDFCF937C
:10318000DF93D52FC42F5527442733272227992390
:10319000D9F09F37C8F0F92F75DF592F482F372FF7
:1031A000262FF63968F411DF2DDFC030CD0721F06E
:1031B00069937993899399939058DF91CF910ACE2F
:1031C0009927882777276627C030CD0721F02993D4
:1031D000399349935993DF91CF9154CFA1DF01D017
:1031E00051CF992339F0552329F09F575F57950FF9
:1031F00013F49AF1C1CF91589F3FE1F3629FA12D43
:103200000F92BB27639FA00DB11DEE27729FA00DEB
:10321000B11DEE1FAF93AA27649FB00DE11D739FF0
:10322000B00DE11DAA1F6627829FB00DE11DA61FEC
:103230005527749FE00DA11D551F839FE00DA11D13
:10324000561F849FA00D511D852F7A2F6E2F1F9022
:103250000F9088231AF4939539F42CCF000C111C8D
:10326000BB1F661F771F881F012808959F939F77B4
:10327000993358F050E449EC3FE02BEDCDDE5FEBA5
:1032800049EC3FE02BEDA6DDDADE5F915078952723
:10329000089597FD0FCF992309F40895482F5ADF19
:1032A000F92FFF57F5959F1B9F1BFF93EBDEFF92B6
:1032B000EF92DF92CF92BF92AF929F928F926B016B
:1032C0007C01405847953327222740685FE3B601C9
:1032D000C70149015A010E949F179401A5010E944C
:1032E000EA164FEF5FEF53D09B01AC0182169306B5
:1032F000A406B50661F78F909F90AF90BF90CF90D6
:10330000DF90EF90FF905F9125DF950FBBCE9B0183
:10331000AC010C94EE181F930F930027192F10780F
:103320009F775FE340E8613071058407950718F0E7
:1033300000680E94BF19912B6F937F938F939F9387
:103340000E948719E0EBF0E0B8DE5F914F913F916A
:103350002F910E94EE18002351F02BED3FE049EC35
:103360005FE300E8902717FD50680E94EA160F916E
:103370001F910895559145913591259108959B018F
:10338000AC019FE380E8772766270C949F17E2DE65
:10339000992359F0AA27940FA51F43F032F04FEF5D
:1033A00050E09417A50714F46DCEE3CE0EF006C0DE
:1033B00000C09FEF80E870E060E008959FE780E83C
:1033C00070E060E00895A1E21A2EAA1BBB1BFD016C
:1033D0000DC0AA1FBB1FEE1FFF1FA217B307E407F4
:1033E000F50720F0A21BB30BE40BF50B661F771F4C
:1033F000881F991F1A9469F760957095809590952C
:103400009B01AC01BD01CF01089597FB092E052654
:103410000ED057FD04D0D7DF0AD0001C38F45095E9
:103420004095309521953F4F4F4F5F4F0895F6F7E8
:1034300090958095709561957F4F8F4F9F4F089520
:1034400009D001921A94E1F7089501900BD01A94D3
:10345000E1F70895F999FECFB2BDA1BDF89A119692
:1034600000B40895F999FECFB2BDA1BD00BC11967C
:0C3470000FB6F894FA9AF99A0FBE08956E
:10347C00B400FFFF01020A0D7468652075736520A6
:10348C006F66207468697320736F667477617265F8
:10349C00206973206F6E6C79207065726D6974741D
:1034AC0065640A0D6F6E206F726967696E616C20BE
:1034BC004D696B726F4B6F707465722D48617264DD
:1034CC0077617265000A0D7777772E4D696B726F95
:1034DC004B6F707465722E646520286329204869CF
:1034EC0053797374656D7320476D62480A0A000D39
:1034FC000D4143432070726573656E740032008811
:10350C00130148656C6C6F20576F726C640000007F
:10351C00000000000000000000000000000000009F
:10352C00000000000000000000000000000000008F
:10353C00000000000000000000000000000000007F
:10354C00000000000000000000000000000000006F
:04355C000000020069
:00000001FF
/tags/V0.23a/twislave.h
New file
0,0 → 1,63
#ifndef _TWI_SLAVE_H_
#define _TWI_SLAVE_H_
 
#include <inttypes.h>
 
#define I2C_SLAVE_ADDRESS 0x50
 
#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
 
 
typedef struct
{
uint8_t Major;
uint8_t Minor;
uint8_t Patch;
uint8_t Compatible;
} I2C_Version_t;
 
typedef struct
{
int16_t MagX;
int16_t MagY;
int16_t MagZ;
} I2C_Mag_t;
 
 
typedef struct
{
int16_t Nick;
int16_t Roll;
} I2C_WriteAttitude_t;
 
 
typedef struct
{
uint8_t CalByte;
uint8_t Dummy1;
uint8_t Dummy2;
} I2C_WriteCal_t;
 
typedef struct
{
int16_t Heading;
} I2C_Heading_t;
 
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;
 
 
void I2C_Init(void);
 
 
#endif // _TWI_SLAVE_H_
 
/tags/V0.23a/menu.c
New file
0,0 → 1,127
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Copyright (c) 04.2007 Holger Buss
// + only for non-profit use
// + www.MikroKopter.com
// + see the File "License.txt" for further Informations
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
#include <stdlib.h>
#include <inttypes.h>
#include "menu.h"
#include "uart.h"
#include "printf_P.h"
#include "analog.h"
#include "main.h"
 
 
uint8_t MaxMenuItem = 2;
uint8_t MenuItem = 0;
 
int8_t DisplayBuff[DISPLAYBUFFSIZE] = "Hello World";
uint8_t DispPtr = 0;
 
 
/************************************/
/* Put Character to LCD Buffer */
/************************************/
void Menu_Putchar(char c)
{
if(DispPtr < DISPLAYBUFFSIZE) DisplayBuff[DispPtr++] = c;
}
 
/************************************/
/* Clear LCD Buffer */
/************************************/
void Menu_Clear(void)
{
uint8_t i;
for( i = 0; i < DISPLAYBUFFSIZE; i++) DisplayBuff[i] = ' ';
}
 
 
/************************************/
/* Update Menu on LCD */
/************************************/
// Display with 20 characters in 4 lines
void Menu_Update(uint8_t Keys)
{
if(Keys & KEY1)
{
if(MenuItem) MenuItem--;
else MenuItem = MaxMenuItem;
}
if(Keys & KEY2)
{
if(MenuItem == MaxMenuItem) MenuItem = 0;
else MenuItem++;
}
if((Keys & KEY1) && (Keys & KEY2)) MenuItem = 0;
 
 
Menu_Clear();
 
if(MenuItem > MaxMenuItem) MenuItem = MaxMenuItem;
// print menu item number in the upper right corner
if(MenuItem < 10)
{
LCD_printfxy(17,0,"[%i]",MenuItem);
}
else
{
LCD_printfxy(16,0,"[%i]",MenuItem);
}
switch(MenuItem)
{
case 0:// Version Info Menu Item
LCD_printfxy(0,0,"++ MK3MAG ++ ");
LCD_printfxy(0,1," V %d.%d%c", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH + 'a');
if(AccPresent)
{
LCD_printfxy(0,2, " ACC Support ");
}
else
{
LCD_printfxy(0,2, " ");
}
LCD_printfxy(0,3,"(c) Buss, Busker ");
break;
 
case 1: // Magnet readings
LCD_printfxy(0,0,"Magnet Sensors: ");
LCD_printfxy(0,1,"X:%+4d Attitude", MagX);
LCD_printfxy(0,2,"Y:%+4d by", MagY);
LCD_printfxy(0,3,"Z:%+4d ", MagZ);
switch(AttitudeSource)
{
case ATTITUDE_SOURCE_I2C: LCD_printfxy(12,2,"I2C"); break;
case ATTITUDE_SOURCE_UART: LCD_printfxy(12,2,"UART"); break;
case ATTITUDE_SOURCE_ACC: LCD_printfxy(12,2,"ACC"); break;
default: LCD_printfxy(12,2,"???"); break;
break;
}
break;
case 2: // Calcstate
LCD_printfxy(0,0,"Calibrating: ");
LCD_printfxy(0,1,"Step: %1d ",ActualCalstate);
switch(ActualCalstate)
{
default:
case 0: LCD_printfxy(0,2," -- "); break;
case 3:
case 1: LCD_printfxy(0,2," pause "); break;
case 2: LCD_printfxy(0,2,"measure horizontal"); break;
case 4: LCD_printfxy(0,2,"measure vertical"); break;
case 5: LCD_printfxy(0,2,"store data"); break;
}
if(!ActualCalstate) LCD_printfxy(13,3,"(start)")
else LCD_printfxy(9,3,"(ESC)(step)");
if(Keys & KEY4) InternalCalstate++;
if(ActualCalstate >= 5 || (Keys & KEY3)) InternalCalstate = 0;
break;
 
default:
MaxMenuItem = MenuItem - 1;
MenuItem = 0;
break;
}
}
/tags/V0.23a/led.c
New file
0,0 → 1,73
/*#######################################################################################
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 / NON-COMMERCIAL USE ONLY
// + www.MikroKopter.com
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Die Portierung oder Nutzung 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 Portierung oder Nutzung der Software (oder Teile davon) auf andere Systeme (ausser der Hardware von www.mikrokopter.de) ist nur
// + mit unserer Zustimmung zulässig
/// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Die Portierung oder Nutzung der Software (oder Teile davon) auf andere Systeme (ausser der Hardware von www.mikrokopter.de) ist nur
// + mit unserer Zustimmung zulässig
/// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + 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 the sources to other systems or using the software on other systems (except 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));
}
 
/tags/V0.23a/timer0.h
New file
0,0 → 1,17
#ifndef _TIMER0_H
#define _TIMER0_H
 
#include <inttypes.h>
 
extern volatile uint16_t CountMilliseconds;
extern volatile uint16_t I2C_Timeout;
 
 
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
 
/tags/V0.23a/analog.h
New file
0,0 → 1,39
#ifndef _ANALOG_H_
#define _ANALOG_H_
 
#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_
 
/tags/V0.23a/led.h
New file
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_
/tags/V0.23a/menu.h
New file
0,0 → 1,30
#ifndef _MENU_H
#define _MENU_H
 
#include <inttypes.h>
#include "printf_P.h"
 
 
#define DISPLAYBUFFSIZE 80
 
 
#define KEY1 0x01
#define KEY2 0x02
#define KEY3 0x04
#define KEY4 0x08
 
extern int8_t DisplayBuff[DISPLAYBUFFSIZE];
extern uint8_t DispPtr;
extern uint8_t MenuItem;
extern uint8_t MaxMenuItem;
 
extern void Menu_Update(uint8_t Keys);
extern void Menu_Putchar(char c);
extern void Menu_Clear(void);
 
#define LCD_printfxy(x,y,format, args...) { DispPtr = y * 20 + x; _printf_P(&Menu_Putchar, PSTR(format) , ## args);}
#define LCD_printf(format, args...) { _printf_P(&Menu_Putchar, PSTR(format) , ## args);}
 
#endif //_MENU_H
 
 
/tags/V0.23a
New file
Property changes:
Added: tsvn:logminsize
## -0,0 +1 ##
+8
\ No newline at end of property