/*#######################################################################################*/
/* !!! THIS IS NOT FREE SOFTWARE !!! */
/*#######################################################################################*/
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + www.MikroKopter.com
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Software Nutzungsbedingungen (english version: see below)
// + der Fa. HiSystems GmbH, Flachsmeerstrasse 2, 26802 Moormerland - nachfolgend Lizenzgeber genannt -
// + Der Lizenzgeber räumt dem Kunden ein nicht-ausschließliches, zeitlich und räumlich* unbeschränktes Recht ein, die im den
// + Mikrocontroller verwendete Firmware für die Hardware Flight-Ctrl, Navi-Ctrl, BL-Ctrl, MK3Mag & PC-Programm MikroKopter-Tool
// + - nachfolgend Software genannt - nur für private Zwecke zu nutzen.
// + Der Einsatz dieser Software ist nur auf oder mit Produkten des Lizenzgebers zulässig.
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Die vom Lizenzgeber gelieferte Software ist urheberrechtlich geschützt. Alle Rechte an der Software sowie an sonstigen im
// + Rahmen der Vertragsanbahnung und Vertragsdurchführung überlassenen Unterlagen stehen im Verhältnis der Vertragspartner ausschließlich dem Lizenzgeber zu.
// + Die in der Software enthaltenen Copyright-Vermerke, Markenzeichen, andere Rechtsvorbehalte, Seriennummern sowie
// + sonstige der Programmidentifikation dienenden Merkmale dürfen vom Kunden nicht verändert oder unkenntlich gemacht werden.
// + Der Kunde trifft angemessene Vorkehrungen für den sicheren Einsatz der Software. Er wird die Software gründlich auf deren
// + Verwendbarkeit zu dem von ihm beabsichtigten Zweck testen, bevor er diese operativ einsetzt.
// + Die Haftung des Lizenzgebers wird - soweit gesetzlich zulässig - begrenzt in Höhe des typischen und vorhersehbaren
// + Schadens. Die gesetzliche Haftung bei Personenschäden und nach dem Produkthaftungsgesetz bleibt unberührt. Dem Lizenzgeber steht jedoch der Einwand
// + des Mitverschuldens offen.
// + Der Kunde trifft angemessene Vorkehrungen für den Fall, dass die Software ganz oder teilweise nicht ordnungsgemäß arbeitet.
// + Er wird die Software gründlich auf deren Verwendbarkeit zu dem von ihm beabsichtigten Zweck testen, bevor er diese operativ einsetzt.
// + Der Kunde wird er seine Daten vor Einsatz der Software nach dem Stand der Technik sichern.
// + Der Kunde ist darüber unterrichtet, dass der Lizenzgeber seine Daten im zur Vertragsdurchführung erforderlichen Umfang
// + und auf Grundlage der Datenschutzvorschriften erhebt, speichert, verarbeitet und, sofern notwendig, an Dritte übermittelt.
// + *) Die räumliche Nutzung bezieht sich nur auf den Einsatzort, nicht auf die Reichweite der programmierten Software.
// + #### ENDE DER NUTZUNGSBEDINGUNGEN ####'
// + Hinweis: Informationen über erweiterte Nutzungsrechte (wie z.B. Nutzung für nicht-private Zwecke) sind auf Anfrage per Email an info(@)hisystems.de verfügbar.
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Software LICENSING TERMS
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + of HiSystems GmbH, Flachsmeerstrasse 2, 26802 Moormerland, Germany - the Licensor -
// + The Licensor grants the customer a non-exclusive license to use the microcontroller firmware of the Flight-Ctrl, Navi-Ctrl, BL-Ctrl, and MK3Mag hardware
// + (the Software) exclusively for private purposes. The License is unrestricted with respect to time and territory*.
// + The Software may only be used with the Licensor's products.
// + The Software provided by the Licensor is protected by copyright. With respect to the relationship between the parties to this
// + agreement, all rights pertaining to the Software and other documents provided during the preparation and execution of this
// + agreement shall be the property of the Licensor.
// + The information contained in the Software copyright notices, trademarks, other legal reservations, serial numbers and other
// + features that can be used to identify the program may not be altered or defaced by the customer.
// + The customer shall be responsible for taking reasonable precautions
// + for the safe use of the Software. The customer shall test the Software thoroughly regarding its suitability for the
// + intended purpose before implementing it for actual operation. The Licensor's liability shall be limited to the extent of typical and
// + foreseeable damage to the extent permitted by law, notwithstanding statutory liability for bodily injury and product
// + liability. However, the Licensor shall be entitled to the defense of contributory negligence.
// + The customer will take adequate precautions in the case, that the software is not working properly. The customer will test
// + the software for his purpose before any operational usage. The customer will backup his data before using the software.
// + The customer understands that the Licensor collects, stores and processes, and, where required, forwards, customer data
// + to third parties to the extent necessary for executing the agreement, subject to applicable data protection and privacy regulations.
// + *) The territory aspect only refers to the place where the Software is used, not its programmed range.
// + #### END OF LICENSING TERMS ####
// + Note: For information on license extensions (e.g. commercial use), please contact us at info(@)hisystems.de.
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "91x_lib.h"
#include "i2c.h"
#include "uart1.h"
#include "timer1.h"
#include "eeprom.h"
#include "led.h"
#include "crc16.h"
#include "main.h"
#include "spi_slave.h"
#include "params.h"
// The EEPROM M24C64 (64k) ist connected via I2C1 interface to the controller.
#define EEPROM_I2C I2C1
// The E0, E2, E3 pins are set to low. Therefore the slave adressbits b3, b2, b1 are 0.
#define EEPROM_I2C_ADDRESS 0xA0
#define EEPROM_SIZE 65536L // 64k bytes
#define EEPROM_WRITE 1
#define EEPROM_READ 0
// timing
#define I2C_IDLE_TIMEOUT 150 // 150 ms
#define I2C_TRANSFER_TIMEOUT 150 // 150 ms
#define I2C_ACCESS_RETRYS 20 // retry 20 times
// globals for rx handler
volatile u8
*EEPROM_pData
= 0;
volatile u16 EEPROM_DataLen
= 0;
// rx data handler for eeprom data read access
void EEPROM_RxDataHandler
(u8
* pRxBuffer
, u8 RxBufferSize
)
{ // if number of byte are matching
if((RxBufferSize
== EEPROM_DataLen
))
{ //copy data from primary buffer to target buffer
if(EEPROM_pData
) memcpy((u8
*)EEPROM_pData
, pRxBuffer
, EEPROM_DataLen
);
}
}
// ----------------------------------------------------------------------------------------
EEPROM_Result_t EEPROM_Transfer
(u8 Direction
, u16 Address
, u8
*pData
, u16 DataLen
)
{
u16 i
;
u8 retry
= 0;
EEPROM_Result_t retval
= EEPROM_ERROR_UNKNOWN
;
if(((u32
)Address
+ (u32
)DataLen
) >= (EEPROM_SIZE
- 1))
{
retval
= EEPROM_ERROR_OUT_OF_ADDRESS_RANGE
;
return(retval
);
}
if((DataLen
+2) > I2C_BUFFER_LEN
)
{
retval
= EEPROM_I2C_BUFFER_OVERRUN
;
return(retval
);
}
do
{
if(!I2CBus_LockBuffer
(EEPROM_I2C
, I2C_IDLE_TIMEOUT
)) return EEPROM_ERROR_I2C_IDLE_TIMEOUT
;
// buffer is now locked
u8 TxBytes
= 0;
u8 TxData
[255];
// transmitt address
TxData
[TxBytes
++] = (u8
)(0x00FF & (Address
>>8));
TxData
[TxBytes
++] = (u8
)(0x00FF & Address
);
if(Direction
== EEPROM_WRITE
)
{ // copy data to i2c transfer buffer
for(i
= 0; i
<DataLen
;i
++)
{
TxData
[TxBytes
++] = pData
[i
];
}
// prepare pointer to rx data
EEPROM_pData
= 0;
EEPROM_DataLen
= 0;
// start transmission
if(!I2CBus_Transmission
(EEPROM_I2C
, EEPROM_I2C_ADDRESS
, TxData
, TxBytes
, 0, 0))
{
return(retval
);
}
}
else // Direction == EEPROM_READ
{
// prepare pointer to rx data
EEPROM_pData
= pData
;
EEPROM_DataLen
= DataLen
;
// start transmission
if(!I2CBus_Transmission
(EEPROM_I2C
, EEPROM_I2C_ADDRESS
, TxData
, TxBytes
, &EEPROM_RxDataHandler
, DataLen
))
{
return(retval
);
}
}
//wait for end of this transfer
if(I2CBus_WaitForEndOfTransmission
(EEPROM_I2C
, I2C_TRANSFER_TIMEOUT
))
{
if(I2CBus
(EEPROM_I2C
)->Error
== I2C_ERROR_NONE
) return(EEPROM_SUCCESS
);
else retval
= EEPROM_DATA_TRANSFER_INCOMPLETE
;
}
else// i2c transfer timed out
{
return(EEPROM_ERROR_I2C_TRANSFER_TIMEOUT
);
}
// or retry
} while(++retry
< I2C_ACCESS_RETRYS
);
return(retval
);
}
EEPROM_Result_t EEPROM_WriteBlock
(u16 Address
, u8
*pData
, u16 DataLen
)
{
u16 len
;
EEPROM_Result_t retval
;
// there can be 32 bytes written in a single cycle if the adresses are locates in the same row
// i.e. the upper 11 bits of the addres are constant
#define EEPROM_WRITE_BLOCK_SIZE 32
len
= EEPROM_WRITE_BLOCK_SIZE
- Address
%EEPROM_WRITE_BLOCK_SIZE
; // number of bytes to match the next row
if(len
>= DataLen
) len
= DataLen
; // do not write more than neccesarry
do
{
retval
= EEPROM_Transfer
(EEPROM_WRITE
, Address
, pData
, len
);
Address
+= len
; // Address of the next row
pData
+= len
; // pointer to start of next data block
DataLen
-= len
; // reduce the number of to be transmitted
if(DataLen
> EEPROM_WRITE_BLOCK_SIZE
) len
= EEPROM_WRITE_BLOCK_SIZE
; // limit next block size to 32
else len
= DataLen
;
}
while(DataLen
&& (retval
== EEPROM_SUCCESS
)); // repeat until all data have been sent and no error has occured
return(retval
);
}
// a data block can be subsequently read after setting the start address once
EEPROM_Result_t EEPROM_ReadBlock
(u16 Address
, u8
*pData
, u16 DataLen
)
{
EEPROM_Result_t retval
= EEPROM_ERROR_UNKNOWN
;
u16 AdrOffset
= 0;
u16 RxLen
;
while(DataLen
> 0)
{
if(DataLen
> I2C_BUFFER_LEN
- 2) RxLen
= I2C_BUFFER_LEN
- 2;
else RxLen
= DataLen
;
retval
= EEPROM_Transfer
(EEPROM_READ
, Address
+AdrOffset
, &(pData
[AdrOffset
]), RxLen
);
if(retval
!= EEPROM_SUCCESS
) break;
AdrOffset
+= RxLen
;
DataLen
-= RxLen
;
}
return(retval
);
}
u8 EEPROM_Init
(void)
{
u8 data
[20];
u8 i
, retval
= 0;
UART1_PutString
("\r\n EEprom init..");
// check if data can be read from eeprom
for(i
=0;i
<10;i
++)
{
UART1_Putchar
('.');
if(EEPROM_SUCCESS
== EEPROM_ReadBlock
(0, data
, 20)) retval
= 1;
if(retval
) break;
}
if(retval
) UART1_PutString
("ok");
else UART1_PutString
("failed !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
return(retval
);
}
void WriteOemNameToEEPROM
(void)
{
char msg
[100];
u16 crc
,crc2
;
EEPROM_Result_t retval
= EEPROM_ERROR_UNKNOWN
;
memcpy(OEM_String
,&LicensePtr
[OEM_IN_LICENSE
], OEM_NAME_LENGHT
);
if(LicensePtr
[OEM_IN_LICENSE
] == 0)
{
OEM_String
[0] = 255; // that is a command to erease the OEM-string
LicensePtr
[OEM_IN_LICENSE
] = 255;
UART1_PutString
("\r\n Erase OEM-String\r\n ");
}
else
{
if(UART_VersionInfo.
HWMajor >= 30) SendOemName
= 1;
UART1_PutString
("\r\n Write OEM-String: ");sprintf(msg
, "(%s)\r\n",OEM_String
);UART1_PutString
(msg
);
//sprintf(msg, "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x \n\r",OEM_String[0],OEM_String[1],OEM_String[2],OEM_String[3],OEM_String[4],OEM_String[5],OEM_String[6],OEM_String[7],OEM_String[8],OEM_String[9],OEM_String[10],OEM_String[11],OEM_String[12],OEM_String[13],OEM_String[14],OEM_String[15]); UART1_PutString(msg);
}
crc
= 2; // Kompatibliaet
crc
+= CRC16
(OEM_String
,16);
EEPROM_ReadBlock
(EEPROM_ADR_OEM_Name_CRC
,(u8
*)&crc2
,2);
if((crc
!= crc2
) || (crc
== 0xffff))
{
retval
= EEPROM_WriteBlock
(EEPROM_ADR_OEM_Name
,OEM_String
,OEM_NAME_LENGHT
);
if(retval
== EEPROM_SUCCESS
) EEPROM_WriteBlock
(EEPROM_ADR_OEM_Name_CRC
,(u8
*)&crc
,2);
}
}
u8 ReadOemNameFromEEPROM
(void)
{
u8 retval
= 0, tmp
;
u16 crc
, crc2
;
tmp
= EEPROM_ReadBlock
(EEPROM_ADR_OEM_Name
,OEM_String
,OEM_NAME_LENGHT
);
if(EEPROM_SUCCESS
== tmp
) retval
= 1;
crc
= 2;
crc
+= CRC16
(OEM_String
,16);
EEPROM_ReadBlock
(EEPROM_ADR_OEM_Name_CRC
,(u8
*)&crc2
,2);
if((crc
== crc2
) && OEM_String
[0] != 0 && OEM_String
[0] != 0xff)
{
memcpy(&LicensePtr
[OEM_IN_LICENSE
],OEM_String
, OEM_NAME_LENGHT
);
SendOemName
= 1;
return(1);
}
else
{
OEM_String
[0] = 255; // delete
return(0);
}
}
void WriteLicenseToEEPROM
(u8 kompatibel
)
{
u16 crc
,crc2
;
EEPROM_Result_t retval
= EEPROM_ERROR_UNKNOWN
;
if(LicensePtr
[OEM_IN_LICENSE
] != 255) WriteOemNameToEEPROM
(); // then we have a OEM name to write
crc
= kompatibel
;
crc
+= CRC16
(LicensePtr
,LICENSE_SIZE_TEXT
);
EEPROM_ReadBlock
(EEPROM_ADR_LICENSE_DATA_CRC
,(u8
*)&crc2
,2);
if((crc
!= crc2
) || (crc
== 0xffff))
{
retval
= EEPROM_WriteBlock
(EEPROM_ADR_LICENSE_DATA
,LicensePtr
,LICENSE_SIZE_TEXT
);
if(retval
== EEPROM_SUCCESS
) EEPROM_WriteBlock
(EEPROM_ADR_LICENSE_DATA_CRC
,(u8
*)&crc
,2);
}
}
void ClearLicenseText
(void)
{
u32 i
;
for(i
=0; i
< LICENSE_SIZE_TEXT
;i
++) LicensePtr
[i
] = 0; //Achtung: das leert die ganze Struktur, nicht nur den Namen
}
void DeleteLicenseInEEPROM
(void)
{
ClearLicenseText
();
WriteLicenseToEEPROM
(0);
}
u8 ReadLicenseFromEEPROM
(void)
{
u8 retval
= 0, tmp
;
u16 crc
, crc2
;
tmp
= EEPROM_ReadBlock
(EEPROM_ADR_LICENSE_DATA
,LicensePtr
,LICENSE_SIZE_TEXT
);
if(EEPROM_SUCCESS
== tmp
) retval
= 1;
crc
= EEPROM_LICENSE_DATA_KOMPATIBEL
;
crc
+= CRC16
(LicensePtr
,LICENSE_SIZE_TEXT
);
EEPROM_ReadBlock
(EEPROM_ADR_LICENSE_DATA_CRC
,(u8
*)&crc2
,2);
if(crc
!= crc2
) retval
++;
if(retval
&& LicensePtr
[0] != 0 && LicensePtr
[0] != 0xff)
{
return(1);
}
else
{
ClearLicenseText
();
return(0);
}
}
void WriteBaroCalibrationToEEprom
(void)
{
#define BARO_KOMPATIBLE 1
s16 data
[2];
data
[0] = LuftdruckTemperaturKompensation
;
data
[1] = data
[0] + BARO_KOMPATIBLE
;
EEPROM_WriteBlock
(EEPROM_ADR_BARO_KALIBRATION
,(u8
*)&data
,4);
NCParams
[NCPARAMS_BARO_KOMPENSATION
] = LuftdruckTemperaturKompensation
;
NCParamState
[NCPARAMS_BARO_KOMPENSATION
] = NCRARAM_STATE_VALID
;
}
void ReadBaroCalibrationfromEEprom
(void)
{
s16 data
[2];
EEPROM_ReadBlock
(EEPROM_ADR_BARO_KALIBRATION
,(u8
*)&data
,4);
if(data
[0] + BARO_KOMPATIBLE
== data
[1])
{
LuftdruckTemperaturKompensation
= data
[0];
if(abs(LuftdruckTemperaturKompensation
) > 250) LuftdruckTemperaturKompensation
= 0;
}
NCParams
[NCPARAMS_BARO_KOMPENSATION
] = LuftdruckTemperaturKompensation
;
NCParamState
[NCPARAMS_BARO_KOMPENSATION
] = NCRARAM_STATE_VALID
;
if(LuftdruckTemperaturKompensation
) UART1_PutString
(" Baro Temperature Calibration active\r\n");
}
void WriteBaudrateIndexToEEprom
(void)
{
u8 data
[2];
#define BAUD_KOMPATIBLE 1
data
[0] = ToFcBaudrateIndex
;
data
[1] = ToFcBaudrateIndex
+ BAUD_KOMPATIBLE
;
EEPROM_WriteBlock
(EEPROM_ADR_BAUDRATE_INDEX
,(u8
*)&data
,2);
// UART1_PutString(" EE-BD-WRITE:"); UART1_Putchar('0'+ToFcBaudrateIndex);
}
void ReadBaudrateIndexfromEEprom
(void)
{
u8 data
[2];
EEPROM_ReadBlock
(EEPROM_ADR_BAUDRATE_INDEX
,(u8
*)&data
,2);
if(data
[0] + BAUD_KOMPATIBLE
== data
[1])
{
ToFcBaudrateIndex
= data
[0];
Uart1Baudrate
= BAUDRATES
[ToFcBaudrateIndex
];
// UART1_PutString(" EE-BD-OK:"); UART1_Putchar('0'+ToFcBaudrateIndex);
}
else UART1_PutString
(" EE-BD-ERR ");
}