// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Copyright (c) 04.2007 Holger Buss
// + Nur für den privaten Gebrauch
// + www.MikroKopter.com
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Es gilt für das gesamte Projekt (Hardware, Software, Binärfiles, Sourcecode und Dokumentation),
// + dass eine Nutzung (auch auszugsweise) nur für den privaten und nicht-kommerziellen Gebrauch zulässig ist.
// + Sollten direkte oder indirekte kommerzielle Absichten verfolgt werden, ist mit uns (info@mikrokopter.de) Kontakt
// + bzgl. der Nutzungsbedingungen aufzunehmen.
// + Eine kommerzielle Nutzung ist z.B.Verkauf von MikroKoptern, Bestückung und Verkauf von Platinen oder Bausätzen,
// + Verkauf von Luftbildaufnahmen, usw.
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + 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 Medien veröffentlicht werden, muss unsere Webseite "http://www.mikrokopter.de"
// + eindeutig als Ursprung verlinkt und genannt 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 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.
// + * 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 example: selling of MikroKopters, selling of PCBs, assembly, ...) is only permitted
// + with our written permission
// + * If sources or documentations are redistributet on other webpages, out webpage (http://www.MikroKopter.de) must be
// + clearly linked as origin
// + * porting to systems other than hardware from www.mikrokopter.de is not allowed
// + 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.
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#ifndef EEMEM
#define EEMEM __attribute__ ((section (".eeprom")))
#endif
#include "eeprom.h"
#include "printf_P.h"
#include "output.h"
#include <avr/eeprom.h>
// byte array in eeprom
uint8_t EEPromArray
[E2END
+ 1] EEMEM
;
/***************************************************/
/* Read Parameter from EEPROM as byte */
/***************************************************/
uint8_t getParamByte
(uint16_t param_id
) {
return eeprom_read_byte
(&EEPromArray
[EEPROM_ADR_PARAM_BEGIN
+ param_id
]);
}
/***************************************************/
/* Write Parameter to EEPROM as byte */
/***************************************************/
void setParamByte
(uint16_t param_id
, uint8_t value
) {
eeprom_write_byte
(&EEPromArray
[EEPROM_ADR_PARAM_BEGIN
+ param_id
], value
);
}
/***************************************************/
/* Read Parameter from EEPROM as word */
/***************************************************/
/*
uint16_t getParamWord(uint16_t param_id) {
return eeprom_read_word((uint16_t *) &EEPromArray[EEPROM_ADR_PARAM_BEGIN
+ param_id]);
}
*/
/***************************************************/
/* Write Parameter to EEPROM as word */
/***************************************************/
/*
void setParamWord(uint16_t param_id, uint16_t value) {
eeprom_write_word((uint16_t *) &EEPromArray[EEPROM_ADR_PARAM_BEGIN + param_id], value);
}
*/
uint16_t CRC16
(uint8_t* data
, uint16_t length
) {
uint16_t crc
= 0;
for (uint16_t i
=0; i
<length
; i
++) {
crc
= (uint8_t)(crc
>> 8) | (crc
<< 8);
crc
^= data
[i
];
crc
^= (uint8_t)(crc
& 0xff) >> 4;
crc
^= (crc
<< 8) << 4;
crc
^= ((crc
& 0xff) << 4) << 1;
}
return crc
;
}
// offset is where the checksum is stored, offset+1 is the revision number, and offset+2... are the data.
// length is the length of the pure data not including checksum and revision number.
void writeChecksummedBlock
(uint8_t revisionNumber
, uint8_t* data
, uint16_t offset
, uint16_t length
) {
uint16_t CRC
= CRC16
(data
, length
);
eeprom_write_byte
(&EEPromArray
[offset
], CRC
&0xff);
eeprom_write_byte
(&EEPromArray
[offset
+1], CRC
>>8);
eeprom_write_byte
(&EEPromArray
[offset
+2], revisionNumber
);
eeprom_write_block
(data
, &EEPromArray
[offset
+3], length
);
}
// offset is where the checksum is stored, offset+1 is the revision number, and offset+2... are the data.
// length is the length of the pure data not including checksum and revision number.
uint8_t readChecksummedBlock
(uint8_t revisionNumber
, uint8_t* target
, uint16_t offset
, uint16_t length
) {
uint16_t CRCRead
= eeprom_read_byte
(&EEPromArray
[offset
]) | (eeprom_read_byte
(&EEPromArray
[offset
+1])<<8);
uint8_t revisionNumberRead
= eeprom_read_byte
(&EEPromArray
[offset
+2]);
eeprom_read_block
(target
, &EEPromArray
[offset
+3], length
);
uint16_t CRCCalculated
= CRC16
(target
, length
);
uint8_t CRCError
= (CRCRead
!= CRCCalculated
);
uint8_t revisionMismatch
= (revisionNumber
!= revisionNumberRead
);
if (CRCError
&& revisionMismatch
) printf("\n\rEEPROM CRC error and revision mismatch; ");
else if (CRCError
) printf("\n\rEEPROM CRC error; ");
else if (revisionMismatch
) printf("\n\rEEPROM revision mismatch; ");
return (CRCError
|| revisionMismatch
);
}
/***************************************************/
/* Read Parameter Set from EEPROM */
/***************************************************/
// setnumber [1..5]
uint8_t paramSet_readFromEEProm
(uint8_t setnumber
) {
uint16_t offset
= EEPROM_ADR_PARAMSET_BEGIN
+ (setnumber
-1)*(sizeof(ParamSet_t
)+EEPROM_CHECKSUMMED_BLOCK_OVERHEAD
);
// output_init(); // what's that doing here??
return readChecksummedBlock
(EEPARAM_REVISION
, (uint8_t*)&staticParams
, offset
, sizeof(ParamSet_t
));
}
/***************************************************/
/* Write Parameter Set to EEPROM */
/***************************************************/
void paramSet_writeToEEProm
(uint8_t setnumber
) {
uint16_t offset
= EEPROM_ADR_PARAMSET_BEGIN
+ (setnumber
-1)*(sizeof(ParamSet_t
)+EEPROM_CHECKSUMMED_BLOCK_OVERHEAD
);
writeChecksummedBlock
(EEPARAM_REVISION
, (uint8_t*)&staticParams
, offset
, sizeof(ParamSet_t
));
// set this parameter set to active set
setActiveParamSet
(setnumber
);
// output_init(); // what's that doing here??
}
void paramSet_readOrDefault
() {
uint8_t setnumber
= getActiveParamSet
();
// parameter version check
if (setnumber
<1 ||setnumber
>5 || paramSet_readFromEEProm
(setnumber
)) {
// if version check faild
printf("\n\rwriting default parameter sets");
for (uint8_t i
=5; i
>0; i
--) {
paramSet_default
(i
);
paramSet_writeToEEProm
(i
);
}
// default-Setting is parameter set 3
setActiveParamSet
(1);
}
printf("\n\r\rUsing Parameter Set %d", getActiveParamSet
());
}
/***************************************************/
/* MixerTable */
/***************************************************/
void mixerMatrix_writeToEEProm
(void) {
writeChecksummedBlock
(EEMIXER_REVISION
, (uint8_t*)&mixerMatrix
, EEPROM_ADR_MIXER_TABLE
, sizeof(mixerMatrix_t
));
}
void mixerMatrix_readOrDefault
(void) {
// load mixer table
if (readChecksummedBlock
(EEMIXER_REVISION
, (uint8_t*)&mixerMatrix
, EEPROM_ADR_MIXER_TABLE
, sizeof(mixerMatrix_t
))) {
printf("writing default mixerMatrix");
mixerMatrix_default
(); // Quadro
mixerMatrix_writeToEEProm
();
}
// determine motornumber
requiredMotors
= 0;
for (uint8_t i
=0; i
<MAX_MOTORS
; i
++) {
if (mixerMatrix.
motor[i
][MIX_THROTTLE
])
requiredMotors
++;
}
printf("\n\rMixer-Config: '%s' (%u Motors)",mixerMatrix.
name, requiredMotors
);
printf("\n\r===================================");
}
/***************************************************/
/* ChannelMap */
/***************************************************/
void channelMap_writeToEEProm
(void) {
writeChecksummedBlock
(CHANNELMAP_REVISION
, (uint8_t*)&channelMap
, EEPROM_ADR_CHANNELMAP
, sizeof(channelMap_t
));
}
void channelMap_readOrDefault
(void) {
if (readChecksummedBlock
(CHANNELMAP_REVISION
, (uint8_t*)&channelMap
, EEPROM_ADR_CHANNELMAP
, sizeof(channelMap_t
))) {
printf("writing default channel map");
channelMap_default
();
channelMap_writeToEEProm
();
}
}
/***************************************************/
/* Sensor offsets */
/***************************************************/
uint8_t gyroAmplifierOffset_readFromEEProm
(void) {
return readChecksummedBlock
(SENSOROFFSET_REVISION
, (uint8_t*)&gyroAmplifierOffset
, EEPROM_ADR_GYROAMPLIFIER
, sizeof(sensorOffset_t
));
}
void gyroAmplifierOffset_writeToEEProm
(void) {
return writeChecksummedBlock
(SENSOROFFSET_REVISION
, (uint8_t*)&gyroAmplifierOffset
, EEPROM_ADR_GYROAMPLIFIER
, sizeof(sensorOffset_t
));
}
uint8_t gyroOffset_readFromEEProm
(void) {
return readChecksummedBlock
(SENSOROFFSET_REVISION
, (uint8_t*)&gyroOffset
, EEPROM_ADR_GYROOFFSET
, sizeof(sensorOffset_t
));
}
void gyroOffset_writeToEEProm
(void) {
writeChecksummedBlock
(SENSOROFFSET_REVISION
, (uint8_t*)&gyroOffset
, EEPROM_ADR_GYROOFFSET
, sizeof(sensorOffset_t
));
}
uint8_t accOffset_readFromEEProm
(void) {
return readChecksummedBlock
(SENSOROFFSET_REVISION
, (uint8_t*)&accOffset
, EEPROM_ADR_ACCOFFSET
, sizeof(sensorOffset_t
));
}
void accOffset_writeToEEProm
(void) {
writeChecksummedBlock
(SENSOROFFSET_REVISION
, (uint8_t*)&accOffset
, EEPROM_ADR_ACCOFFSET
, sizeof(sensorOffset_t
));
}
/***************************************************/
/* Get active parameter set */
/***************************************************/
uint8_t getActiveParamSet
(void) {
uint8_t setnumber
;
setnumber
= eeprom_read_byte
(&EEPromArray
[PID_ACTIVE_SET
]);
if (setnumber
> 4) {
setActiveParamSet
(setnumber
= 0);
}
return setnumber
;
}
/***************************************************/
/* Set active parameter set */
/***************************************************/
void setActiveParamSet
(uint8_t setnumber
) {
eeprom_write_byte
(&EEPromArray
[PID_ACTIVE_SET
], setnumber
);
}