Subversion Repositories NaviCtrl

Compare Revisions

Ignore whitespace Rev 27 → Rev 28

/branches/V0.1 killagreg/uart.h
File deleted
/branches/V0.1 killagreg/GPSUart.c
File deleted
/branches/V0.1 killagreg/GPSUart.h
File deleted
/branches/V0.1 killagreg/uart.c
File deleted
/branches/V0.1 killagreg/GPS.c
1,252 → 1,377
/*#######################################################################################*/
/* !!! THIS IS NOT FREE SOFTWARE !!! */
/*#######################################################################################*/
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Copyright (c) 2008 Ingo Busker, Holger Buss
// + Nur für den privaten Gebrauch
// + FOR NON COMMERCIAL USE ONLY
// + 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 (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 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 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 permitted
// + 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
// + * If sources or documentations are redistributet on other webpages, out webpage (http://www.MikroKopter.de) must be
// + clearly linked as origin
// + * PORTING this software (or part of it) 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.
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "91x_lib.h"
#include "main.h"
#include "uart.h"
#include "uart1.h"
#include "ubx.h"
#include "GPS.h"
#include "fat16.h"
#include "timer.h"
#include "spi_slave.h"
 
u8 OsdBar; // Direction home for OSD
s16 OsdDistance; // Distance home
#define M_PI_180 (M_PI / 180.0f)
#define GPS_UPDATETIME_MS 200 // 200ms or 5Hz
 
GPSStick_t GPSStick;
GPSParameter_t GPSParameter;
typedef enum
{
GPS_FLIGHT_MODE_UNDEF,
GPS_FLIGHT_MODE_FREE,
GPS_FLIGHT_MODE_AID,
GPS_FLIGHT_MODE_HOME,
} FlightMode_t;
 
u8 logtext[100];
typedef struct
{
float Gain;
float P;
float I;
float D;
float ACC;
u8 MinSat;
s8 StickThreshold;
FlightMode_t FlightMode;
} __attribute__((packed)) GPS_Parameter_t;
 
typedef enum
typedef struct
{
GPS_MODE_FREE,
GPS_MODE_AID,
GPS_MODE_HOLD,
GPS_MODE_HOME,
} GpsFlightMode_t;
s32 North;
s32 East;
s32 Bearing;
s32 Distance;
} __attribute__((packed)) GPS_Deviation_t;
 
GpsFlightMode_t GpsFlightMode = GPS_MODE_FREE;
GPS_Stick_t GPS_Stick;
GPS_Parameter_t GPS_Parameter;
GPS_Deviation_t TargetDeviation;
 
// the reference positions
GPS_Pos_t GPSTargetPosition = {0,0,0, INVALID};
GPS_Pos_t GPSTHomePosition = {0,0,0, INVALID};
GPS_Pos_t PCGPSTargetPosition = {0,0,0, INVALID};
u8 OsdBar = 0;
u8 OsdDistance = 0;
 
 
// the gps reference positions
GPS_Pos_t GPSHoldPosition = {0,0,0, INVALID};
GPS_Pos_t GPSHomePosition = {0,0,0, INVALID};
GPS_Pos_t GPSPCPosition = {0,0,0, INVALID};
GPS_Pos_t *pTargetPosition = NULL;
 
//-------------------------------------------------------------
// Update GPSParamter
void GPS_UpdateParameter(void)
{
static FlightMode_t FlightMode_Old = GPS_FLIGHT_MODE_UNDEF;
// in case of bad receiving conditions
if(FC.RC_Quality < 100)
{ // set fixed parameter
GPS_Parameter.FlightMode = GPS_FLIGHT_MODE_FREE;
GPS_Parameter.Gain = (100);
GPS_Parameter.P = (float) (90);
GPS_Parameter.I = (float) (90);
GPS_Parameter.D = (float) (90);
GPS_Parameter.ACC = (float) (90);
GPS_Parameter.MinSat = 6;
GPS_Parameter.StickThreshold = 8;
 
}
else
{
// update paramter from FC
if (Parameter.NaviGpsModeControl < 50) GPS_Parameter.FlightMode = GPS_FLIGHT_MODE_AID;
else if(Parameter.NaviGpsModeControl < 180) GPS_Parameter.FlightMode = GPS_FLIGHT_MODE_FREE;
else GPS_Parameter.FlightMode = GPS_FLIGHT_MODE_HOME;
GPS_Parameter.Gain = (float) (Parameter.NaviGpsGain);
GPS_Parameter.P = (float) (Parameter.NaviGpsP);
GPS_Parameter.I = (float) (Parameter.NaviGpsI);
GPS_Parameter.D = (float) (Parameter.NaviGpsD);
GPS_Parameter.ACC = (float) (Parameter.NaviGpsACC);
GPS_Parameter.MinSat = (u8)Parameter.NaviGpsMinSat;
GPS_Parameter.StickThreshold = (s8)Parameter.NaviStickThreshold;
}
// FlightMode changed?
if(GPS_Parameter.FlightMode != FlightMode_Old) BeepTime = 100; // beep to indicate that mode has switched
FlightMode_Old = GPS_Parameter.FlightMode;
}
 
//-------------------------------------------------------------
// This function defines a good GPS signal condition
u8 GPS_IsSignalOK(void)
{
static u8 GPSFix = 0;
if( (GPSData.Status != INVALID) && (GPSData.SatFix == SATFIX_3D) && (GPSData.Flags & FLAG_GPSFIXOK) && ( (GPSData.NumOfSats >= GPS_Parameter.MinSat) || GPSFix) )
{
GPSFix = 1; // if once GPS_SAT_MIN has been found the signal is also OK of the number of sats drops below that value
return(1);
}
else return(0);
}
 
 
//------------------------------------------------------------
// Checks for manual control action
u8 GPS_IsManuallyControlled(void)
{
if(abs(FC.StickNick) > GPS_Parameter.StickThreshold || abs(FC.StickRoll) > GPS_Parameter.StickThreshold) return 1;
else return 0;
}
 
//------------------------------------------------------------
// set position to current GPS position
u8 GPS_SetCurrPosition(GPS_Pos_t * pGPSPos)
{
u8 retval = 0;
if(pGPSPos == NULL) return(retval); // bad pointer
 
if(GPS_IsSignalOK())
{ // is GPS signal condition is fine
pGPSPos->Longitude = GPSData.Longitude;
pGPSPos->Latitude = GPSData.Latitude;
pGPSPos->Altitude = GPSData.Altitude;
pGPSPos->Status = NEWDATA;
retval = 1;
}
else
{ // bad GPS signal condition
pGPSPos->Status = INVALID;
retval = 0;
}
return(retval);
}
 
//------------------------------------------------------------
// clear position data
u8 GPS_ClearPosition(GPS_Pos_t * pGPSPos)
{
u8 retval = 0;
if(pGPSPos == NULL) return(retval); // bad pointer
else
{
pGPSPos->Longitude = 0;
pGPSPos->Latitude = 0;
pGPSPos->Altitude = 0;
pGPSPos->Status = INVALID;
retval = 1;
}
return (retval);
}
 
 
//------------------------------------------------------------
void GPS_Neutral()
{
GPSStick.Nick = 0;
GPSStick.Roll = 0;
GPSStick.Yaw = 0;
GPS_Stick.Nick = 0;
GPS_Stick.Roll = 0;
GPS_Stick.Yaw = 0;
}
 
//------------------------------------------------------------
// Init variables or send configuration to GPS module
void GPS_Init(void)
{
SerialPutString("\r\nGPS init...");
UBX_Init();
GPS_Neutral();
GPS_ClearPosition(&GPSHoldPosition);
GPS_ClearPosition(&GPSHomePosition);
GPS_ClearPosition(&GPSPCPosition);
pTargetPosition = NULL;
SerialPutString("ok");
}
 
OsdDistance = 0;
OsdBar = 0;
//------------------------------------------------------------
// calculates the bearing to target position from its deviation
s32 DirectionToTarget_N_E(float northdev, float eastdev)
{
s32 bearing;
bearing = (s32)(atan2(northdev, eastdev) / M_PI_180);
bearing = (270 - bearing)%360;
return(bearing);
}
 
GPSParameter.P = 100;
GPSParameter.I = 100;
GPSParameter.D = 100;
GPSParameter.ACC = 100;
GPSParameter.ModeSwitch = 100;
GPSParameter.Amplification = 100;
//------------------------------------------------------------
// transform the integer deg into float radians
inline double RadiansFromGPS(s32 deg)
{
return ((double)deg * 1e-7 * M_PI_180); // 1E-7 because deg is the value in ° * 1E7
}
 
GpsFlightMode = GPS_MODE_FREE;
//------------------------------------------------------------
// transform the integer deg into float deg
inline double DegFromGPS(s32 deg)
{
return ((double)deg * 1e-7); // 1E-7 because deg is the value in ° * 1E7
}
//-----------------------------------------------------------------------
void LogGPSData(void)
 
//------------------------------------------------------------
// calculate the deviation from the given target position
u8 GPS_CalculateDeviation( GPS_Pos_t * pTargetPos)
{
static u32 Flushtime = 0;
static File_t *GPSLogFile = 0;
s16 i1, i2, i3;
double temp1, temp2;
// if given pointer is NULL
if(pTargetPos == NULL) goto baddata;
// if data of given target position are invalid
if(pTargetPos->Status == INVALID) goto baddata;
// if current GPS Signal is not sufficient
if(!GPS_IsSignalOK()) goto baddata;
// The deviation from the target position along north and east direction is
// simple the lat/lon difference. To convert that angular deviation into an
// arc length the spherical projection has to be considered.
// The mean earth radius is 6371km. Therfore the arc length per latitude degree
// is always 6371km * 2 * Pi / 360deg = 111.2 km/deg.
// The arc length per longitude degree depends on the correspondig latitude and
// is 111.2km * cos(latitude).
 
if((GPSData.Status != INVALID) && (GPSData.SatFix == SATFIX_3D))
{
// if logfile is not opened
if(!GPSLogFile)
{
GPSLogFile = fopen_("/LOG/GPSLOG.TXT", 'a');
if(GPSLogFile) SerialPutString("Opening GPSLog\r\n");
Flushtime = SetDelay(5000L); // every 5 seconds
// calculate the shortest longitude deviation from target
temp1 = DegFromGPS(GPSData.Longitude) - DegFromGPS(pTargetPos->Longitude);
// outside an angular difference of -180 deg ... +180 deg it shorter to go the other way around
// In our application we wont fly more than 20.000 km but along the date line this is important.
if(temp1 > 180.0f) temp1 -= 360.0f;
else if (temp1 < -180.0f) temp1 += 360.0f;
// calculate latitude deviation from target
// this is allways within -180 deg ... 180 deg */
temp1 *= cos(RadiansFromGPS(pTargetPos->Latitude));
temp2 = DegFromGPS(GPSData.Latitude) - DegFromGPS(pTargetPos->Latitude);
// deviation from target position in cm
TargetDeviation.North = (s32)(11119492.7 * temp2);
TargetDeviation.East = (s32)(11119492.7 * temp1);
 
}
// if logfile
if(GPSLogFile)
{
sprintf(logtext,"%02d/%02d/%04d %02d:%02d:%02d.%03d\t", SystemTime.Month, SystemTime.Day, SystemTime.Year, SystemTime.Hour, SystemTime.Min, SystemTime.Sec, SystemTime.mSec );
fputs_(logtext, GPSLogFile);
i1 = (s16)(GPSData.Longitude/10000000L);
i2 = abs((s16)((GPSData.Longitude%10000000L)/10000L));
i3 = abs((s16)(((GPSData.Longitude%10000000L)%10000L)/10L));
sprintf(logtext,"%03d.%.3d%.3d\t",i1, i2, i3);
fputs_(logtext, GPSLogFile);
i1 = (s16)(GPSData.Latitude/10000000L);
i2 = abs((s16)((GPSData.Latitude%10000000L)/10000L));
i3 = abs((s16)(((GPSData.Latitude%10000000L)%10000L)/10L));
sprintf(logtext,"%03d.%.3d%.3d\t",i1, i2, i3);
fputs_(logtext, GPSLogFile);
i1 = (s16)(GPSData.Altitude/1000L);
i2 = abs((s16)(GPSData.Altitude%1000L));
sprintf(logtext,"%d.%.3d\r\n",i1, i2);
fputs_(logtext, GPSLogFile);
if(CheckDelay(Flushtime))
{
fflush_(GPSLogFile);
Flushtime = SetDelay(5000L); // every 5 seconds
}
}
}
// If the position deviation is small enough to neglect the earth curvature
// (this is for our application always fulfilled) the distance to target
// can be calculated by the pythagoras of north and east deviation.
TargetDeviation.Distance = (s32)(11119492.7f * hypot(temp1, temp2));
if (TargetDeviation.Distance == 0L) TargetDeviation.Bearing = 0L;
else TargetDeviation.Bearing = DirectionToTarget_N_E(temp2, temp1);
return(1);
 
baddata:
TargetDeviation.North = 0L;
TargetDeviation.East = 0L;
TargetDeviation.Distance = 0L;
TargetDeviation.Bearing = 0L;
return(0);
}
 
//------------------------------------------------------------
 
u8 Navigation(void)
void GPS_Navigation(void)
{
static GpsFlightMode_t oldGpsFlightMode = GPS_MODE_FREE;
static u32 beep_rythm;
static u32 GPSDataTimeout = 0;
 
beep_rythm++;
 
// update paramter
GPSParameter.ModeSwitch = Parameter.User1;
GPSParameter.Amplification = (float) Parameter.User2 / (100.0);
GPSParameter.P = (float) Parameter.User3;
GPSParameter.I = (float) Parameter.User4;
GPSParameter.D = (float) Parameter.User5;
GPSParameter.ACC = (float) Parameter.User6;
// in case of bad receiving conditions
if(FC.RC_Quality < 100)
{ // set fixed parameter
GPSParameter.ModeSwitch = 0;
GPSParameter.Amplification = 100;
GPSParameter.P = (float) 90;
GPSParameter.I = (float) 90;
GPSParameter.D = (float) 90;
GPSParameter.ACC = (float) 90;
}
 
// update GPS Parameter from FC-Data via SPI interface
GPS_UpdateParameter();
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+ GPS-Mode Selection
//+ Check for new data from GPS-receiver
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
oldGpsFlightMode = GpsFlightMode;
if(GPSParameter.ModeSwitch < 50) GpsFlightMode = GPS_MODE_AID;
else if(GPSParameter.ModeSwitch < 180) GpsFlightMode = GPS_MODE_FREE;
else GpsFlightMode = GPS_MODE_HOME;
// Mode changed?
if(GpsFlightMode != oldGpsFlightMode) BeepTime = 100; // indicate that mode has switched
 
// look for new data from GPS
switch(GPSData.Status)
{
case INVALID: // no gps data available
// do nothing
break;
case NEWDATA: // handle new gps data
// wait maximum of 3 times the normal data update time
GPSDataTimeout = SetDelay(3*GPSData.UpdateTime);
LogGPSData(); // write gps position to file
// set debug values
DebugOut.Analog[21] = (s16)GPSData.Speed_North;
DebugOut.Analog[22] = (s16)GPSData.Speed_East;
DebugOut.Analog[31] = GPSData.NumOfSats;
// wait maximum of 3 times the normal data update time before data timemout
GPSDataTimeout = SetDelay(3* GPS_UPDATETIME_MS);
beep_rythm++;
 
// debug
DebugOut.Analog[21] = (u16)GPSData.Speed_North;
DebugOut.Analog[22] = (u16)GPSData.Speed_East;
DebugOut.Analog[31] = (u16)GPSData.NumOfSats;
// If GPS signal condition is sufficient for a reliable position measurement
if(GPS_IsSignalOK())
{
// if calibration on fc is active
if(FC.MKFlags & MKFLAG_CALIBRATE)
{ // set home position to current position
if (GPS_SetCurrPosition(&GPSHomePosition)) BeepTime = 700;
}
// update home position from serial data
#define MAX_TARGET_DISTANCE 30000 // 300m
if(GPSPCPosition.Status == NEWDATA)
{
// calculate distance to transmitted position
if(GPS_CalculateDeviation(&GPSPCPosition))
{ // if distance is within the limit
if(TargetDeviation.Distance <= MAX_TARGET_DISTANCE)
{ // update home position
GPSHomePosition.Status = INVALID;
GPSHomePosition.Latitude = GPSPCPosition.Latitude;
GPSHomePosition.Longitude = GPSPCPosition.Longitude;
GPSHomePosition.Altitude = GPSPCPosition.Altitude;
GPSHomePosition.Status = NEWDATA;
GPSPCPosition.Status = PROCESSED;
BeepTime = 700;
}
}
}
 
// check for current flight mode
switch(GPS_Parameter.FlightMode)
{
case GPS_FLIGHT_MODE_FREE:
GPS_SetCurrPosition(&GPSHoldPosition);
pTargetPosition = NULL;
break;
case GPS_FLIGHT_MODE_AID:
if(GPS_IsManuallyControlled())
{
GPS_SetCurrPosition(&GPSHoldPosition);
pTargetPosition = NULL;
}
else
{
pTargetPosition = &GPSHoldPosition;
}
break;
case GPS_FLIGHT_MODE_HOME:
if(GPSHomePosition.Status == INVALID)
{
pTargetPosition = &GPSHoldPosition; // fall back to hold mode if home position is not available
BeepTime = 255;
}
else // home position is valid
{
pTargetPosition = &GPSHomePosition;
}
break;
 
case GPS_FLIGHT_MODE_UNDEF:
default:
// no target position
GPS_SetCurrPosition(&GPSHoldPosition);
pTargetPosition = NULL;
break;
}
 
// calculate deviation from target position
if(GPS_CalculateDeviation(pTargetPosition))
{
// put your control loop algorithm here to update the members of GPS_Stick
// using the the GPS_Parameter and TargetDeviation.
GPS_Neutral();
}
 
}// eof if GPSSignalOK
else // GPSSignal not OK
{
GPS_Neutral();
// beep if signal is not sufficient
if(!(GPSData.Flags & FLAG_GPSFIXOK) && !(beep_rythm % 5)) BeepTime = 100;
else if (GPSData.NumOfSats < GPS_Parameter.MinSat && !(beep_rythm % 5)) BeepTime = 10;
}
GPSData.Status = PROCESSED; // mark as processed
break;
case PROCESSED:
 
case PROCESSED: // the current data have been allready processed
// if no new data are available within the timeout switch to invalid state.
if(CheckDelay(GPSDataTimeout)) GPSData.Status = INVALID;
break;
}
 
 
 
if((GPSData.Status != INVALID)) // there are valid data from the GPS
{
 
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+ Fix okay and enough sats
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
if((GPSData.Flags & FLAG_GPSFIXOK) && (GPSData.NumOfSats >= GPS_SAT_MIN))
{
// here is a good place to put your GPS code...
GPSStick.Nick = 0; // do nothing
GPSStick.Roll = 0; // do nothing
}
else
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+ No Fix or not enough sats
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
{
GPS_Neutral(); // disable gps control
/*
if(!(GPSData.Flags & FLAG_GPSFIXOK) && !(beep_rythm % 5)) BeepTime = 100;
else if (GPSData.NumOfSats < GPS_SAT_MIN && !(beep_rythm % 5)) BeepTime = 10;*/
}
}
else // GPS Data are invalid
{
GPS_Neutral(); // disable gps control
}
 
DebugOut.Analog[29] = GPSStick.Nick;
DebugOut.Analog[30] = GPSStick.Roll;
 
return (0);
return;
}
 
/branches/V0.1 killagreg/GPS.h
1,11 → 1,8
#ifndef __GPS_H
#define __GPS_H
 
#include "91x_lib.h"
#include "GPSUart.h"
#include "ubx.h"
 
#define GPS_SAT_MIN 6
 
typedef struct
{
s32 Longitude;
12,41 → 9,27
s32 Latitude;
s32 Altitude;
Status_t Status;
} GPS_Pos_t;
} __attribute__((packed)) GPS_Pos_t;
 
extern GPS_Pos_t GPSTargetPosition;
extern GPS_Pos_t GPSTHomePosition;
extern GPS_Pos_t PCGPSTargetPosition;
extern GPS_Pos_t GPSPCPosition;
extern GPS_Pos_t GPSHomePosition;
extern GPS_Pos_t * pTargetPosition;
 
 
typedef struct
{
float Amplification;
float P;
float I;
float D;
float ACC;
s32 ModeSwitch;
} __attribute__((packed)) GPSParameter_t;
 
extern GPSParameter_t GPSParameter;
 
extern u8 OsdBar;
extern s16 OsdDistance;
 
typedef struct
{
s16 Nick;
s16 Roll;
s16 Yaw;
} __attribute__((packed)) GPSStick_t;
} __attribute__((packed)) GPS_Stick_t;
 
extern GPSStick_t GPSStick;
extern GPS_Stick_t GPS_Stick;
 
extern void GPS_Navigation(void);
extern void GPS_Init(void);
 
extern u8 OsdBar;
extern u8 OsdDistance;
 
extern u8 Navigation(void);
extern void GPS_Init(void);
 
#endif //__GPS_H
 
#endif
/branches/V0.1 killagreg/Navi-Ctrl.Uv2
11,7 → 11,6
Group (USB-Lib)
 
File 1,1,<.\main.c><main.c>
File 1,1,<.\uart.c><uart.c>
File 1,1,<.\interrupt.c><interrupt.c>
File 1,1,<.\ramfunc.c><ramfunc.c>
File 1,1,<.\menu.c><menu.c>
20,7 → 19,6
File 1,1,<.\spi_slave.c><spi_slave.c>
File 1,1,<.\i2c.c><i2c.c>
File 1,1,<.\GPS.c><GPS.c>
File 1,1,<.\GPSUart.c><GPSUart.c>
File 1,1,<.\usb.c><usb.c>
File 1,1,<.\fat16.c><fat16.c>
File 1,1,<.\sdc.c><sdc.c>
33,9 → 31,12
File 1,1,<.\usb_pwr.c><usb_pwr.c>
File 1,1,<.\led.c><led.c>
File 1,1,<.\crc16.c><crc16.c>
File 1,1,<.\ubx.c><ubx.c>
File 1,1,<.\uart0.c><uart0.c>
File 1,1,<.\uart1.c><uart1.c>
File 1,1,<.\kml.c><kml.c>
File 2,5,<.\ramfunc.h><ramfunc.h>
File 2,5,<.\main.h><main.h>
File 2,5,<.\uart.h><uart.h>
File 2,5,<.\menu.h><menu.h>
File 2,5,<.\printf_P.h><printf_P.h>
File 2,5,<.\settings.h><settings.h>
42,7 → 43,6
File 2,5,<.\timer.h><timer.h>
File 2,5,<.\usb.h><usb.h>
File 2,5,<.\spi_slave.h><spi_slave.h>
File 2,5,<.\GPSUart.h><GPSUart.h>
File 2,5,<.\i2c.h><i2c.h>
File 2,5,<.\sdc.h><sdc.h>
File 2,5,<.\ssc.h><ssc.h>
51,6 → 51,11
File 2,5,<.\libstr91x\include\91x_lib.h><91x_lib.h>
File 2,5,<.\led.h><led.h>
File 2,5,<.\crc16.h><crc16.h>
File 2,5,<.\ubx.h><ubx.h>
File 2,5,<.\uart0.h><uart0.h>
File 2,5,<.\uart1.h><uart1.h>
File 2,5,<.\kml_header.h><kml_header.h>
File 2,5,<.\kml.h><kml.h>
File 3,2,<.\startup912.s><startup912.s>
File 4,1,<.\libstr91x\src\91x_scu.c><91x_scu.c>
File 4,1,<.\libstr91x\src\91x_gpio.c><91x_gpio.c>
/branches/V0.1 killagreg/fat16.c
59,7 → 59,7
#include "timer.h"
#include "fat16.h"
#include "sdc.h"
#include "uart.h"
#include "uart1.h"
 
 
//________________________________________________________________________________________________________________________________________
132,24 → 132,32
*/
 
// Partition Types:
#define PART_TYPE_UNKNOWN 0x00
#define PART_TYPE_FAT12 0x01
#define PART_TYPE_XENIX 0x02
#define PART_TYPE_DOSFAT16 0x04
#define PART_TYPE_EXTDOS 0x05
#define PART_TYPE_FAT16 0x06
#define PART_TYPE_NTFS 0x07
#define PART_TYPE_FAT32 0x0B
#define PART_TYPE_FAT32LBA 0x0C
#define PART_TYPE_FAT16LBA 0x0E
#define PART_TYPE_EXTDOSLBA 0x0F
#define PART_TYPE_ONTRACK 0x33
#define PART_TYPE_NOVELL 0x40
#define PART_TYPE_PCIX 0x4B
#define PART_TYPE_PHOENIXSAVE 0xA0
#define PART_TYPE_CPM 0xDB
#define PART_TYPE_DBFS 0xE0
#define PART_TYPE_BBT 0xFF
#define PART_TYPE_UNKNOWN 0x00
#define PART_TYPE_FAT12 0x01
#define PART_TYPE_XENIX 0x02
#define PART_TYPE_FAT16_ST_32_MB 0x04
#define PART_TYPE_EXTDOS 0x05
#define PART_TYPE_FAT16_LT_32_MB 0x06
#define PART_TYPE_NTFS 0x07
#define PART_TYPE_FAT32 0x0B
#define PART_TYPE_FAT32LBA 0x0C
#define PART_TYPE_FAT16LBA 0x0E
#define PART_TYPE_EXTDOSLBA 0x0F
#define PART_TYPE_EISA 0x12
#define PART_TYPE_ONTRACK 0x33
#define PART_TYPE_NOVELL 0x40
#define PART_TYPE_DYNAMIC 0x42
#define PART_TYPE_PCIX 0x4B
#define PART_TYPE_LINUX_SWAP 0x82
#define PART_TYPE_LINUX_NATIVE 0x83
#define PART_TYPE_LINUX_LVM 0x8E
#define PART_TYPE_PHOENIXSAVE 0xA0
#define PART_TYPE_FREEBSD 0xA5
#define PART_TYPE_OPENBSD 0xA6
#define PART_TYPE_NETNBSD 0xA9
#define PART_TYPE_CPM 0xDB
#define PART_TYPE_DBFS 0xE0
#define PART_TYPE_BBT 0xFF
 
 
/*
185,7 → 193,7
typedef struct
{
u8 JumpCode[3]; // Jump Code + NOP
u8 OEMName[8]; // OEM Name
s8 OEMName[8]; // OEM Name
u16 BytesPerSector; // Bytes Per Sector
u8 SectorsPerCluster; // Sectors Per Cluster
u16 ReservedSectors; // Reserved Sectors
201,8 → 209,8
u16 DriveNo; // Logical Drive Number of Partition
u8 ExtendedSig; // Extended Signature (0x29)
u32 SerialNo; // Serial Number of the Partition
u8 VolumeName[11]; // Volume Name of the Partititon
u8 FATName[8]; // FAT Name (FAT16)
s8 VolumeName[11]; // Volume Name of the Partititon
s8 FATName[8]; // FAT Name (FAT16)
u8 ExecutableCode[446]; // 446 bytes for machine start code
u16 ExecutableMarker; // Executable Marker (0x55 0xAA)
} __attribute__((packed)) VBR_Entry_t;
219,7 → 227,7
*/
typedef struct
{
u8 Name[8]; // 8 bytes name, padded with spaces.
s8 Name[8]; // 8 bytes name, padded with spaces.
u8 Extension[3]; // 3 bytes extension, padded with spaces.
u8 Attribute; // attribute of the directory entry (unused,archive,read-only,system,directory,volume)
u8 Reserved[10]; // reserved bytes within the directory entry.
344,34 → 352,34
}
 
/****************************************************************************************************************************************/
/* Function: UnlockFilePointer(File_t *); */
/* Function: UnlockFilePointer(file_t *); */
/* */
/* Description: This function trys to unlock a file pointer. */
/* */
/* Returnvalue: Returns 1 if file pointer was freed else 0. */
/****************************************************************************************************************************************/
u8 UnlockFilePointer(File_t * File)
u8 UnlockFilePointer(File_t * file)
{
u8 cnt;
if(File == 0) return(0);
if(file == NULL) return(0);
for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++)
{
if(&FilePointer[cnt] == File) // filepointer to be freed found?
if(&FilePointer[cnt] == file) // filepointer to be freed found?
{
File->State = FSTATE_UNUSED;
File->FirstSectorOfFirstCluster = 0; // Sectorpointer to the first sector of the first datacluster of the file.
File->FirstSectorOfCurrCluster = 0;
File->SectorOfCurrCluster = 0; // Pointer to the cluster which is edited at the moment.
File->SectorOfCurrCluster = 0; // The sector which is edited at the moment (cluster_pointer + sector_index).
File->ByteOfCurrSector = 0; // The bytelocation within the current sector (cluster_pointer + sector_index + byte_index).
File->Mode = 0; // mode of fileoperation (read,write)
File->Size = 0; // the size of the opend file in bytes.
File->Position = 0; // pointer to a character within the file 0 < fileposition < filesize
File->SectorInCache = 0; // the last sector read, wich is still in the sectorbuffer.
File->DirectorySector = 0; // the sectorposition where the directoryentry has been made.
File->DirectoryIndex = 0; // the index to the directoryentry within the specified sector.
File->Attribute = 0; // the attribute of the file opened.
File = 0;
file->State = FSTATE_UNUSED;
file->FirstSectorOfFirstCluster = 0; // Sectorpointer to the first sector of the first datacluster of the file.
file->FirstSectorOfCurrCluster = 0;
file->SectorOfCurrCluster = 0; // Pointer to the cluster which is edited at the moment.
file->SectorOfCurrCluster = 0; // The sector which is edited at the moment (cluster_pointer + sector_index).
file->ByteOfCurrSector = 0; // The bytelocation within the current sector (cluster_pointer + sector_index + byte_index).
file->Mode = 0; // mode of fileoperation (read,write)
file->Size = 0; // the size of the opend file in bytes.
file->Position = 0; // pointer to a character within the file 0 < fileposition < filesize
file->SectorInCache = 0; // the last sector read, wich is still in the sectorbuffer.
file->DirectorySector = 0; // the sectorposition where the directoryentry has been made.
file->DirectoryIndex = 0; // the index to the directoryentry within the specified sector.
file->Attribute = 0; // the attribute of the file opened.
file = NULL;
return(1);
}
}
379,17 → 387,17
}
 
/****************************************************************************************************************************************/
/* Function: SeperateDirName(u8*, u8*, u8*); */
/* Function: SeperateDirName(s8*, s8*); */
/* */
/* Description: This function seperates the first dirname from filepath and brings them */
/* into the needed format ('test.txt' -> 'TEST TXT') */
/* The subpath is the pointer to the remaining substring if the filepath */
/* */
/* Returnvalue: Return 0 on error ot pointer to subpath */
/* Returnvalue: Return 0 on error or pointer to subpath */
/****************************************************************************************************************************************/
u8* SeperateDirName(const u8 *filepath, u8 *dirname)
s8* SeperateDirName(const s8 *filepath, s8 *dirname)
{
u8* subpath = 0;
s8* subpath = 0;
u8 readpointer = 0;
u8 writepointer = 0;
 
401,12 → 409,13
{
if(((filepath[readpointer] == 0) || (filepath[readpointer] == '/'))) // if '/' found or end of filepath reached
{
subpath = (u8*)&filepath[readpointer]; // store the position of the first "/" found after the beginning of the filenpath
subpath = (s8*)&filepath[readpointer]; // store the position of the first "/" found after the beginning of the filenpath
}
readpointer++;
}
 
// clear dirname with spaces
dirname[11] = 0; // terminate dirname
for(writepointer = 0; writepointer < 11; writepointer++) dirname[writepointer] = ' ';
writepointer = 0;
// start seperating the dirname from the filepath.
417,12 → 426,12
if(writepointer >= 11) return 0; // dirname to long
if(filepath[readpointer] == '.') // seperating dirname and extension.
{
if(writepointer<8)
if(writepointer <= 8)
{
readpointer++; // next character in filename
writepointer = 8; // jump to start of extension
readpointer++; // next character in filename
writepointer = 8; // jump to start of extension
}
else return (0); // dirbasename to long
else return (0); // dirbasename to long
}
else
{
508,12 → 517,14
u8 Fat16_Init(void)
{
u8 cnt = 0;
u32 PartitionFirstSector;
u32 partitionfirstsector;
VBR_Entry_t *VBR;
MBR_Entry_t *MBR;
File_t *File;
u8 result;
File_t *file;
u8 result = 0;
 
 
SerialPutString("\r\n FAT16 init...");
Partition.IsValid = 0;
 
// declare the filepointers as unused.
522,37 → 533,34
FilePointer[cnt].State = FSTATE_UNUSED;
}
// set current file pinter to first position in list
File = &FilePointer[0];
file = &FilePointer[0];
// try to initialise the sd-card.
cnt = 0;
while(SD_SUCCESS != SDC_Init())
if(SD_SUCCESS != SDC_Init())
{
if(cnt > 3)
{
SerialPutString("SD-Card could not be initialized.\r\n");
result = 1;
goto end;
}
cnt++;
SerialPutString("SD-Card could not be initialized.");
result = 1;
goto end;
}
 
// SD-Card is initialized successfully
if(SD_SUCCESS != SDC_GetSector((u32)MBR_SECTOR,File->Cache)) // Read the MasterBootRecord
if(SD_SUCCESS != SDC_GetSector((u32)MBR_SECTOR,file->Cache)) // Read the MasterBootRecord
{
SerialPutString("Error reading the MBR.\r\n");
SerialPutString("Error reading the MBR.");
result = 2;
goto end;
}
MBR = (MBR_Entry_t *)File->Cache; // Enter the MBR using the structure MBR_Entry_t.
if(MBR->PartitionEntry1.Type == PART_TYPE_FAT16)
MBR = (MBR_Entry_t *)file->Cache; // Enter the MBR using the structure MBR_Entry_t.
if((MBR->PartitionEntry1.Type == PART_TYPE_FAT16_ST_32_MB) ||
(MBR->PartitionEntry1.Type == PART_TYPE_FAT16_LT_32_MB) ||
(MBR->PartitionEntry1.Type == PART_TYPE_FAT16LBA))
{
// get sector offset 1st partition
PartitionFirstSector = MBR->PartitionEntry1.NoSectorsBeforePartition;
partitionfirstsector = MBR->PartitionEntry1.NoSectorsBeforePartition;
// Start of Partition is the Volume Boot Sector
if(SD_SUCCESS != SDC_GetSector(PartitionFirstSector,File->Cache)) // Read the volume boot record
if(SD_SUCCESS != SDC_GetSector(partitionfirstsector,file->Cache)) // Read the volume boot record
{
SerialPutString("Error reading the VBR.\r\n");
SerialPutString("Error reading the VBR.");
result = 3;
goto end;
}
559,13 → 567,13
}
else // maybe the medium has no partition assuming sector 0 is the vbr
{
PartitionFirstSector = 0;
partitionfirstsector = 0;
}
VBR = (VBR_Entry_t *) File->Cache; // Enter the VBR using the structure VBR_Entry_t.
VBR = (VBR_Entry_t *) file->Cache; // Enter the VBR using the structure VBR_Entry_t.
if(VBR->BytesPerSector != BYTES_PER_SECTOR)
{
SerialPutString("VBR: Sector size not supported.\r\n");
SerialPutString("VBR: Sector size not supported.");
result = 4;
goto end;
}
577,7 → 585,7
/* Calculate the sectorpositon of the FAT, the Rootdirectory and the first Datacluster. */
// Calculate the position of the FileAllocationTable:
// Start + # of Reserved Sectors
Partition.FirstFatSector = (u32)(PartitionFirstSector + (u32)(VBR->ReservedSectors));
Partition.FirstFatSector = (u32)(partitionfirstsector + (u32)(VBR->ReservedSectors));
// Calculate the position of the Rootdirectory:
// Start + # of Reserved Sectors + (# of Sectors Per FAT * # of FAT Copies)
Partition.FirstRootDirSector = Partition.FirstFatSector + (u32)((u32)Partition.SectorsPerFat*(u32)Partition.FatCopies);
587,7 → 595,7
// Calculate the last data sector
if(VBR->NoSectors == 0)
{
SerialPutString("VBR: Bad number of sectors.\r\n");
SerialPutString("VBR: Bad number of sectors.");
result = 5;
goto end;
}
595,7 → 603,7
// check for FAT16 in VBR of first partition
if(!((VBR->FATName[0]=='F') && (VBR->FATName[1]=='A') && (VBR->FATName[2]=='T') && (VBR->FATName[3]=='1')&&(VBR->FATName[4]=='6')))
{
SerialPutString("VBR: Partition ist not FAT16 type.\r\n");
SerialPutString("VBR: Partition ist not FAT16 type.");
result = 6;
goto end;
}
603,6 → 611,7
result = 0;
end:
if(result != 0) Fat16_Deinit();
else SerialPutString("ok");
return(result);
}
 
609,24 → 618,24
 
 
/****************************************************************************************************************************************/
/* Function: ClearCurrCluster(File_t file); */
/* Function: ClearCurrCluster(File_t*); */
/* */
/* Description: This function fills the current cluster with 0. */
/* */
/* Returnvalue: The function returns 1 on success else 0. */
/****************************************************************************************************************************************/
u8 ClearCurrCluster(File_t * File)
u8 ClearCurrCluster(File_t * file)
{
u8 retvalue = 1;
u32 i;
if((!Partition.IsValid) || (File == 0)) return(0);
if((!Partition.IsValid) || (file == NULL)) return(0);
 
for(i = 0; i < BYTES_PER_SECTOR; i++) File->Cache[i] = 0; // clear file cache
for(i = 0; i < BYTES_PER_SECTOR; i++) file->Cache[i] = 0; // clear file cache
for(i = 0; i < Partition.SectorsPerCluster; i++)
{
File->SectorInCache = File->FirstSectorOfCurrCluster + i;
if(SD_SUCCESS != SDC_PutSector(File->SectorInCache, File->Cache))
file->SectorInCache = file->FirstSectorOfCurrCluster + i;
if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
{
Fat16_Deinit();
retvalue = 0;
636,24 → 645,24
}
 
/*****************************************************************************************************************************************/
/* Function: GetNextCluster(File_t file); */
/* Function: GetNextCluster(File_t* ); */
/* */
/* Description: This function finds the next datacluster of the file specified with File *File. */
/* */
/* Returnvalue: The function returns the next cluster or 0 if the last cluster has already reached. */
/*****************************************************************************************************************************************/
u16 GetNextCluster(File_t * File)
u16 GetNextCluster(File_t * file)
{
u16 cluster = 0;
u32 fat_byte_offset, sector, byte;
Fat16Entry_t * Fat;
Fat16Entry_t * fat;
if((!Partition.IsValid) || (File == 0)) return(cluster);
if((!Partition.IsValid) || (file == NULL)) return(cluster);
// if sector is within the data area
if((Partition.FirstDataSector <= File->FirstSectorOfCurrCluster)&& (File->FirstSectorOfCurrCluster <= Partition.LastDataSector))
if((Partition.FirstDataSector <= file->FirstSectorOfCurrCluster)&& (file->FirstSectorOfCurrCluster <= Partition.LastDataSector))
{
// determine current file cluster
cluster = SectorToFat16Cluster(File->FirstSectorOfCurrCluster);
cluster = SectorToFat16Cluster(file->FirstSectorOfCurrCluster);
// calculate byte offset in the fat for corresponding entry
fat_byte_offset = ((u32)cluster)<<1; // two FAT bytes (16 bits) for every cluster
// calculate the sector that contains the current cluster within the fat
661,10 → 670,10
// calculate byte offset of the current cluster within that fat sector
byte = fat_byte_offset % BYTES_PER_SECTOR;
// read this sector to the file cache
if(File->SectorInCache != sector)
if(file->SectorInCache != sector)
{
File->SectorInCache = sector; // update sector stored in buffer
if(SD_SUCCESS != SDC_GetSector(File->SectorInCache, File->Cache)) // read sector from sd-card
file->SectorInCache = sector; // update sector stored in buffer
if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache)) // read sector from sd-card
{
Fat16_Deinit();
return (cluster);
671,8 → 680,8
}
}
// read the next cluster from cache
Fat = (Fat16Entry_t *)(&(File->Cache[byte]));
cluster = Fat->NextCluster;
fat = (Fat16Entry_t *)(&(file->Cache[byte]));
cluster = fat->NextCluster;
// if last cluster fat entry
if(FAT16_CLUSTER_LAST_MIN <= cluster)
{
680,9 → 689,9
}
else
{
File->FirstSectorOfCurrCluster = Fat16ClusterToSector(cluster);
File->SectorOfCurrCluster = 0;
File->ByteOfCurrSector = 0;
file->FirstSectorOfCurrCluster = Fat16ClusterToSector(cluster);
file->SectorOfCurrCluster = 0;
file->ByteOfCurrSector = 0;
}
}
return(cluster);
690,21 → 699,21
 
 
/****************************************************************************************************************************************/
/* Function: FindNextFreeCluster(File_t *file); */
/* Function: FindNextFreeCluster(File_t *); */
/* */
/* Description: This function looks in the fat to find the next free cluster */
/* */
/* Returnvalue: The function returns the cluster number of the next free cluster found within the fat. */
/****************************************************************************************************************************************/
u16 FindNextFreeCluster(File_t *File)
u16 FindNextFreeCluster(File_t *file)
{
u32 fat_sector; // current sector within the fat relative to the first sector of the fat.
u32 curr_sector; // current sector
u16 fat_entry; // index to an fatentry within the actual sector (256 fatentries are possible within one sector).
u16 free_cluster = 0; // next free cluster number.
Fat16Entry_t * Fat;
Fat16Entry_t * fat;
if((!Partition.IsValid) || (File == 0)) return(0);
if((!Partition.IsValid) || (file == NULL)) return(0);
 
// start searching for an empty cluster at the beginning of the fat.
fat_sector = 0;
711,21 → 720,21
do
{
curr_sector = Partition.FirstFatSector + fat_sector; // calculate sector to read
File->SectorInCache = curr_sector; // upate the sector number of file cache.
if( SD_SUCCESS != SDC_GetSector(File->SectorInCache, File->Cache)) // read sector of fat from sd-card.
file->SectorInCache = curr_sector; // upate the sector number of file cache.
if( SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache)) // read sector of fat from sd-card.
{
Fat16_Deinit();
return(free_cluster);
}
 
Fat = (Fat16Entry_t *)File->Cache; // set fat pointer to file cache
fat = (Fat16Entry_t *)file->Cache; // set fat pointer to file cache
 
for(fat_entry = 0; fat_entry < FAT16_ENTRIES_PER_SECTOR; fat_entry++) // look for an free cluster at all entries in this sector of the fat.
{
if(Fat[fat_entry].NextCluster == FAT16_CLUSTER_FREE) // empty cluster found!!
if(fat[fat_entry].NextCluster == FAT16_CLUSTER_FREE) // empty cluster found!!
{
Fat[fat_entry].NextCluster = FAT16_CLUSTER_LAST_MAX; // mark this fat-entry as used
if(SD_SUCCESS != SDC_PutSector(File->SectorInCache, File->Cache)) // and save the sector at the sd-card.
fat[fat_entry].NextCluster = FAT16_CLUSTER_LAST_MAX; // mark this fat-entry as used
if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache)) // and save the sector at the sd-card.
{
Fat16_Deinit();
return(free_cluster);
742,18 → 751,18
 
 
/****************************************************************************************************************************************************/
/* Function: s16 fseek_(File *, s32 *, u8) */
/* Function: s16 fseek_(File_t *, s32 *, u8) */
/* */
/* Description: This function sets the pointer of the stream relative to the position */
/* specified by origin (SEEK_SET, SEEK_CUR, SEEK_END) */
/* Returnvalue: Is 1 if seek was successful */
/****************************************************************************************************************************************************/
s16 fseek_(File_t *File, s32 offset, s16 origin)
s16 fseek_(File_t *file, s32 offset, s16 origin)
{
s32 fposition = 0;
s16 retvalue = 1;
if((!Partition.IsValid) || (File == 0)) return(0);
if((!Partition.IsValid) || (file == NULL)) return(0);
switch(origin)
{
case SEEK_SET: // Fileposition relative to the beginning of the file.
760,53 → 769,110
fposition = 0;
break;
case SEEK_END: // Fileposition relative to the end of the file.
fposition = (s32)File->Size;
fposition = (s32)file->Size;
break;
case SEEK_CUR: // Fileposition relative to the current position of the file.
default:
fposition = File->Position;
fposition = file->Position;
break;
}
 
fposition += offset;
 
if((fposition >= 0) && (fposition <= (s32)File->Size)) // is the pointer still within the file?
if((fposition >= 0) && (fposition <= (s32)file->Size)) // is the pointer still within the file?
{
// reset file position to start of the file
File->FirstSectorOfCurrCluster = File->FirstSectorOfFirstCluster;
File->SectorOfCurrCluster = 0;
File->ByteOfCurrSector = 0;
File->Position = 0;
file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
file->SectorOfCurrCluster = 0;
file->ByteOfCurrSector = 0;
file->Position = 0;
 
while(File->Position < fposition) // repeat until the current position is less than target
while(file->Position < fposition) // repeat until the current position is less than target
{
File->Position++; // increment file position
File->ByteOfCurrSector++; // next byte in current sector
if(File->ByteOfCurrSector >= BYTES_PER_SECTOR)
file->Position++; // increment file position
file->ByteOfCurrSector++; // next byte in current sector
if(file->ByteOfCurrSector >= BYTES_PER_SECTOR)
{
File->ByteOfCurrSector = 0; // reading at the beginning of new sector.
File->SectorOfCurrCluster++; // continue reading in next sector
if(File->SectorOfCurrCluster >= Partition.SectorsPerCluster) // if end of cluster is reached, the next datacluster has to be searched in the FAT.
file->ByteOfCurrSector = 0; // reading at the beginning of new sector.
file->SectorOfCurrCluster++; // continue reading in next sector
if(file->SectorOfCurrCluster >= Partition.SectorsPerCluster) // if end of cluster is reached, the next datacluster has to be searched in the FAT.
{
if(GetNextCluster(File)) // Sets the clusterpointer of the file to the next datacluster.
if(GetNextCluster(file)) // Sets the clusterpointer of the file to the next datacluster.
{
File->SectorOfCurrCluster = 0;
file->SectorOfCurrCluster = 0;
}
else // the last cluster was allready reached
{
File->SectorOfCurrCluster--; // jump back to the ast sector in the last cluster
File->ByteOfCurrSector = BYTES_PER_SECTOR; // set ByteOfCurrSector one byte over sector end
file->SectorOfCurrCluster--; // jump back to the ast sector in the last cluster
file->ByteOfCurrSector = BYTES_PER_SECTOR; // set ByteOfCurrSector one byte over sector end
}
}
}
}
}
if(File->Position == fposition) retvalue = 0;
if(file->Position == fposition) retvalue = 0;
return(retvalue);
}
 
 
/****************************************************************************************************************************************/
/* Function: u16 DeleteClusterChain(File *file); */
/* */
/* Description: This function trances along a cluster chain in the fat and frees all clusters visited. */
/* */
/****************************************************************************************************************************************/
u8 DeleteClusterChain(u16 StartCluster)
{
u16 cluster;
u32 fat_byte_offset, sector, byte;
Fat16Entry_t * fat;
u8 buffer[BYTES_PER_SECTOR];
u32 sector_in_buffer = 0;
u8 repeat = 0;
 
if(!Partition.IsValid) return 0;
 
cluster = StartCluster; // init chain trace
// calculate byte offset in the fat for corresponding entry
fat_byte_offset = ((u32)cluster)<<1; // two FAT bytes (16 bits) for every cluster
// calculate the sector that contains the current cluster within the fat
sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
// calculate byte offset of the current cluster within that fat sector
byte = fat_byte_offset % BYTES_PER_SECTOR;
do
{
if(sector != sector_in_buffer)
{
// read this sector to buffer
sector_in_buffer = sector;
if(SD_SUCCESS != SDC_GetSector(sector_in_buffer, buffer)) return 0; // read sector from sd-card
}
// read the next cluster from cache
fat = (Fat16Entry_t *)(&(buffer[byte]));
cluster = fat->NextCluster;
if((FAT16_CLUSTER_USED_MIN <= cluster) && (cluster <= FAT16_CLUSTER_USED_MAX) ) repeat = 1;
else repeat = 0;
 
fat->NextCluster = FAT16_CLUSTER_FREE; // mark current cluster as free
// calculate byte offset in the fat for corresponding entry
fat_byte_offset = ((u32)cluster)<<1; // two FAT bytes (16 bits) for every cluster
// calculate the sector that contains the current cluster within the fat
sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
// calculate byte offset of the current cluster within that fat sector
byte = fat_byte_offset % BYTES_PER_SECTOR;
// if new sector is not the sector in buffer or the last cluster in the chain was traced
if((sector != sector_in_buffer) || !repeat)
{ // write sector in buffer
if(SD_SUCCESS != SDC_PutSector(sector_in_buffer,buffer)) return 0;
}
}
while(repeat);
 
return 1;
}
 
 
/****************************************************************************************************************************************/
/* Function: u16 AppendCluster(File *file); */
/* */
/* Description: This function looks in the fat to find the next free cluster and appends it to the file. */
813,54 → 879,54
/* */
/* Returnvalue: The function returns the appened cluster number or 0 of no cluster was appended. */
/****************************************************************************************************************************************/
u16 AppendCluster(File_t *File)
u16 AppendCluster(File_t *file)
{
u16 last_cluster, new_cluster = 0;
u32 fat_byte_offset, sector, byte;
Fat16Entry_t * Fat;
Fat16Entry_t * fat;
if((!Partition.IsValid) || (File == 0)) return(new_cluster);
if((!Partition.IsValid) || (file == NULL)) return(new_cluster);
 
new_cluster = FindNextFreeCluster(File); // the next free cluster found on the disk.
new_cluster = FindNextFreeCluster(file); // the next free cluster found on the disk.
if(new_cluster)
{ // A free cluster was found and can be added to the end of the file.
fseek_(File, 0, SEEK_END); // jump to the end of the file
last_cluster = SectorToFat16Cluster(File->FirstSectorOfCurrCluster); // determine current file cluster
fseek_(file, 0, SEEK_END); // jump to the end of the file
last_cluster = SectorToFat16Cluster(file->FirstSectorOfCurrCluster); // determine current file cluster
fat_byte_offset = ((u32)last_cluster)<<1;
sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
byte = fat_byte_offset % BYTES_PER_SECTOR;
 
if(File->SectorInCache != sector)
if(file->SectorInCache != sector)
{
File->SectorInCache = sector; // update sector stored in buffer
if(SD_SUCCESS != SDC_GetSector(File->SectorInCache, File->Cache)) // read sector from sd-card
file->SectorInCache = sector; // update sector stored in buffer
if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache)) // read sector from sd-card
{
Fat16_Deinit();
return(0);
}
}
Fat = (Fat16Entry_t *)(&(File->Cache[byte]));
Fat->NextCluster = new_cluster; // append the free cluster to the end of the file in the FAT.
if(SD_SUCCESS != SDC_PutSector(File->SectorInCache, File->Cache)) // save the modified sector to the FAT.
fat = (Fat16Entry_t *)(&(file->Cache[byte]));
fat->NextCluster = new_cluster; // append the free cluster to the end of the file in the FAT.
if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache)) // save the modified sector to the FAT.
{
Fat16_Deinit();
return(0);
}
File->FirstSectorOfCurrCluster = Fat16ClusterToSector(new_cluster);
File->SectorOfCurrCluster = 0;
File->ByteOfCurrSector = 0;
file->FirstSectorOfCurrCluster = Fat16ClusterToSector(new_cluster);
file->SectorOfCurrCluster = 0;
file->ByteOfCurrSector = 0;
}
return(new_cluster);
}
 
/****************************************************************************************************************************************************/
/* Function: DirectoryEntryExist(u8 *, u8, u8, File_t *) */
/* Function: DirectoryEntryExist(s8 *, u8, u8, File_t *) */
/* */
/* Description: This function searches all possible dir entries until the file or directory is found or the end of the directory is reached */
/* */
/* Returnvalue: This function returns 1 if the directory entry specified was found. */
/****************************************************************************************************************************************************/
u8 DirectoryEntryExist(u8 *dirname, u8 attribfilter, u8 attribmask, File_t *File)
u8 DirectoryEntryExist(s8 *dirname, u8 attribfilter, u8 attribmask, File_t *file)
{
u32 dir_sector, max_dir_sector, curr_sector;
u16 dir_entry = 0;
868,45 → 934,45
u16 end_of_directory_not_reached = 0;
u8 i = 0;
u8 direntry_exist = 0;
DirEntry_t * Dir;
DirEntry_t * dir;
 
// if incomming pointers are useless return immediatly
if((!Partition.IsValid) || (File == 0) || (dirname == 0)) return(direntry_exist);
if((!Partition.IsValid) || (file == NULL) || (dirname == NULL)) return(direntry_exist);
 
// dir entries can be searched only in filesclusters that have
// a corresponding dir entry with adir-flag set in its attribute
// or direct within the root directory area
File->FirstSectorOfFirstCluster = 0;
file->FirstSectorOfFirstCluster = 0;
// no current directory exist therefore assume searching in the root
if(File->DirectorySector == 0)
if(file->DirectorySector == 0)
{
max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
File->FirstSectorOfFirstCluster = Partition.FirstRootDirSector;
file->FirstSectorOfFirstCluster = Partition.FirstRootDirSector;
}
// within the root directory area we can read sectors sequentially until the end of this area
else if((Partition.FirstRootDirSector <= File->DirectorySector) && (File->DirectorySector < Partition.FirstDataSector))
else if((Partition.FirstRootDirSector <= file->DirectorySector) && (file->DirectorySector < Partition.FirstDataSector))
{
max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
}
// within the data clusters we can read sectors sequentially only within the cluster
else if((Partition.FirstDataSector <= File->DirectorySector) && (File->DirectorySector <= Partition.LastDataSector))
else if((Partition.FirstDataSector <= file->DirectorySector) && (file->DirectorySector <= Partition.LastDataSector))
{
max_dir_sector = Partition.SectorsPerCluster; // limit max secters before next cluster
}
else return (direntry_exist); // bad sector range for directory sector of the file
// if search area is not defined yet
if(File->FirstSectorOfFirstCluster == 0)
if(file->FirstSectorOfFirstCluster == 0)
{
// check if the directory entry of current file is existent and has the dir-flag set
File->SectorInCache = File->DirectorySector; // update the sector number of file cache.
if(SD_SUCCESS != SDC_GetSector(File->SectorInCache, File->Cache))// read in the sector.
file->SectorInCache = file->DirectorySector; // update the sector number of file cache.
if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
{
Fat16_Deinit();
return(direntry_exist);
}
Dir = (DirEntry_t *)File->Cache; // set pointer to directory
switch(Dir[File->DirectoryIndex].Name[0]) // check if current directory exist
dir = (DirEntry_t *)file->Cache; // set pointer to directory
switch((u8)dir[file->DirectoryIndex].Name[0]) // check if current directory exist
{
case SLOT_EMPTY:
case SLOT_DELETED:
915,19 → 981,19
return (direntry_exist);
break;
default: // and is a real directory
if((Dir[File->DirectoryIndex].Attribute & ATTR_SUBDIRECTORY) != ATTR_SUBDIRECTORY)
if((dir[file->DirectoryIndex].Attribute & ATTR_SUBDIRECTORY) != ATTR_SUBDIRECTORY)
{ // current file is not a directory therefore no file or subdirectory can be created here
return (direntry_exist);
}
break;
}
File->FirstSectorOfFirstCluster = Fat16ClusterToSector(Dir[File->DirectoryIndex].StartCluster);
file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dir[file->DirectoryIndex].StartCluster);
}
 
// update current file data area position to start of first cluster
File->FirstSectorOfCurrCluster = File->FirstSectorOfFirstCluster;
File->SectorOfCurrCluster = 0;
File->ByteOfCurrSector = 0;
file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
file->SectorOfCurrCluster = 0;
file->ByteOfCurrSector = 0;
 
do // loop over all data clusters of the current directory entry
{
934,18 → 1000,18
dir_sector = 0; // reset sector counter within a new cluster
do // loop over all sectors of a cluster or all sectors of the root directory
{
curr_sector = File->FirstSectorOfCurrCluster + dir_sector; // calculate sector number
File->SectorInCache = curr_sector; // upate the sector number of file cache.
if(SD_SUCCESS != SDC_GetSector(File->SectorInCache, File->Cache))// read the sector
curr_sector = file->FirstSectorOfCurrCluster + dir_sector; // calculate sector number
file->SectorInCache = curr_sector; // upate the sector number of file cache.
if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read the sector
{
Fat16_Deinit();
return(direntry_exist);
}
Dir = (DirEntry_t *)File->Cache; // set pointer to directory
dir = (DirEntry_t *)file->Cache; // set pointer to directory
// search all directory entries within that sector
for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++)
{ // check for existing dir entry
switch(Dir[dir_entry].Name[0])
switch((u8)dir[dir_entry].Name[0])
{
case SLOT_EMPTY:
case SLOT_DELETED:
953,20 → 1019,20
break;
default:
// if existing check attributes before names are compared will safe performance
if ((Dir[dir_entry].Attribute & attribmask) != attribfilter) break; // attribute must match
if ((dir[dir_entry].Attribute & attribmask) != attribfilter) break; // attribute must match
// then compare the name to the giveb dirname (first 11 characters include 8 chars of basename and 3 chars extension.)
i = 0;
while((i < 11) && (Dir[dir_entry].Name[i] == dirname[i])) i++;
while((i < 11) && (dir[dir_entry].Name[i] == dirname[i])) i++;
if (i < 10) break; // names does not match
// if dirname and attribute have matched
File->Attribute = Dir[dir_entry].Attribute; // store attribute of found dir entry
File->FirstSectorOfFirstCluster = Fat16ClusterToSector(Dir[dir_entry].StartCluster); // set sector of first data cluster
File->FirstSectorOfCurrCluster = File->FirstSectorOfFirstCluster;
File->SectorOfCurrCluster = 0;
File->ByteOfCurrSector = 0;
File->DirectorySector = curr_sector; // current sector
File->DirectoryIndex = dir_entry; // current direntry in current sector
File->Size = Dir[dir_entry].Size;
file->Attribute = dir[dir_entry].Attribute; // store attribute of found dir entry
file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dir[dir_entry].StartCluster); // set sector of first data cluster
file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
file->SectorOfCurrCluster = 0;
file->ByteOfCurrSector = 0;
file->DirectorySector = curr_sector; // current sector
file->DirectoryIndex = dir_entry; // current direntry in current sector
file->Size = dir[dir_entry].Size;
direntry_exist = 1; // mark as found
dir_entry = DIRENTRIES_PER_SECTOR; // stop for-loop
} // end of first byte of name check
976,9 → 1042,9
}while((dir_sector < max_dir_sector) && (!direntry_exist));
 
// if we are seaching in the data area and the file not found in this cluster so take next cluster.
if(!direntry_exist && ( Partition.FirstDataSector <= File->FirstSectorOfCurrCluster))
if(!direntry_exist && ( Partition.FirstDataSector <= file->FirstSectorOfCurrCluster))
{
end_of_directory_not_reached = GetNextCluster(File); // updates File->FirstSectorOfCurrCluster
end_of_directory_not_reached = GetNextCluster(file); // updates File->FirstSectorOfCurrCluster
}
}while((end_of_directory_not_reached) && (!direntry_exist)); // repeat until a next cluster exist an no
return(direntry_exist);
986,7 → 1052,7
 
 
/****************************************************************************************************************************************/
/* Function: CreateDirectoryEntry(u8 *, u16, File_t *) */
/* Function: CreateDirectoryEntry(s8 *, u16, File_t *) */
/* */
/* Description: This function looks for the next free position in the directory and creates an entry. */
/* The type of an directory entry is specified by the file attribute. */
993,53 → 1059,53
/* */
/* Returnvalue: Return 0 on error */
/****************************************************************************************************************************************/
u8 CreateDirectoryEntry(u8 *dirname, u8 attrib, File_t *File)
u8 CreateDirectoryEntry(s8 *dirname, u8 attrib, File_t *file)
{
u32 dir_sector, max_dir_sector, curr_sector;
u16 dir_entry = 0;
u16 SubDirCluster, DirCluster = 0;
u16 subdircluster, dircluster = 0;
u16 end_of_directory_not_reached = 0;
u8 i = 0;
u8 retvalue = 0;
DirEntry_t *Dir;
DirEntry_t *dir;
 
if((!Partition.IsValid) || (File == 0) || (dirname == 0)) return (retvalue);
if((!Partition.IsValid) || (file == NULL) || (dirname == NULL)) return (retvalue);
// It is not checked here that the dir entry that should be created is already existent!
// Dir entries can be created only in file-clusters that have
// the dir-flag set in its attribute or within the root directory
File->FirstSectorOfFirstCluster = 0;
file->FirstSectorOfFirstCluster = 0;
// no current directory exist therefore assume creating in the root
if(File->DirectorySector == 0)
if(file->DirectorySector == 0)
{
max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
DirCluster = 0;
File->FirstSectorOfFirstCluster = Partition.FirstRootDirSector;
dircluster = 0;
file->FirstSectorOfFirstCluster = Partition.FirstRootDirSector;
}
// within the root directory area we can read sectors sequentially until the end of this area
else if((Partition.FirstRootDirSector <= File->DirectorySector) && (File->DirectorySector < Partition.FirstDataSector))
else if((Partition.FirstRootDirSector <= file->DirectorySector) && (file->DirectorySector < Partition.FirstDataSector))
{
max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
}
// within the data clusters we can read sectors sequentially only within the cluster
else if((Partition.FirstDataSector <= File->DirectorySector) && (File->DirectorySector <= Partition.LastDataSector))
else if((Partition.FirstDataSector <= file->DirectorySector) && (file->DirectorySector <= Partition.LastDataSector))
{
max_dir_sector = Partition.SectorsPerCluster;
}
else return (retvalue); // bad sector range for directory sector of the file
// if search area is not defined yet
if(File->FirstSectorOfFirstCluster == 0)
if(file->FirstSectorOfFirstCluster == 0)
{
// check if the directory entry of current file is existent and has the dir-flag set
File->SectorInCache = File->DirectorySector; // update the sector number of file cache.
if(SD_SUCCESS != SDC_GetSector(File->SectorInCache, File->Cache))// read in the sector.
file->SectorInCache = file->DirectorySector; // update the sector number of file cache.
if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
{
Fat16_Deinit();
return(retvalue);
}
Dir = (DirEntry_t *)File->Cache; // set pointer to directory
switch(Dir[File->DirectoryIndex].Name[0]) // check if current directory exist
dir = (DirEntry_t *)file->Cache; // set pointer to directory
switch((u8)dir[file->DirectoryIndex].Name[0]) // check if current directory exist
{
case SLOT_EMPTY:
case SLOT_DELETED:
1046,83 → 1112,83
return (retvalue);
break;
default: // and is a real directory
if((Dir[File->DirectoryIndex].Attribute & ATTR_SUBDIRECTORY) != ATTR_SUBDIRECTORY)
if((dir[file->DirectoryIndex].Attribute & ATTR_SUBDIRECTORY) != ATTR_SUBDIRECTORY)
{ // current file is not a directory therefore no file or subdirectory can be created here
return (retvalue);
}
break;
}
DirCluster = Dir[File->DirectoryIndex].StartCluster;
File->FirstSectorOfFirstCluster = Fat16ClusterToSector(DirCluster);
dircluster = dir[file->DirectoryIndex].StartCluster;
file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dircluster);
}
SubDirCluster = FindNextFreeCluster(File); // get the next free cluster on the disk and mark it as used.
if(SubDirCluster)
subdircluster = FindNextFreeCluster(file); // get the next free cluster on the disk and mark it as used.
if(subdircluster)
{
File->FirstSectorOfCurrCluster = File->FirstSectorOfFirstCluster;
File->SectorOfCurrCluster = 0;
file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
file->SectorOfCurrCluster = 0;
do // loop over all clusters of current directory
{
dir_sector = 0; // reset sector counter within a new cluster
do // loop over all sectors of a cluster or all sectors of the root directory
{
curr_sector = File->FirstSectorOfCurrCluster + dir_sector; // calculate sector number
File->SectorInCache = curr_sector; // upate the sector number of file cache.
if(SD_SUCCESS != SDC_GetSector(File->SectorInCache, File->Cache))// read in the sector.
curr_sector = file->FirstSectorOfCurrCluster + dir_sector; // calculate sector number
file->SectorInCache = curr_sector; // upate the sector number of file cache.
if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
{
Fat16_Deinit();
return(retvalue);
}
Dir = (DirEntry_t *)File->Cache; // set pointer to directory
dir = (DirEntry_t *)file->Cache; // set pointer to directory
// search all directory entries of a sector
for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++)
{ // check if current direntry is available
if((Dir[dir_entry].Name[0] == SLOT_EMPTY) || (Dir[dir_entry].Name[0] == SLOT_DELETED))
if(((u8)dir[dir_entry].Name[0] == SLOT_EMPTY) || ((u8)dir[dir_entry].Name[0] == SLOT_DELETED))
{ // a free direntry was found
for(i = 0; i < 11; i++) Dir[dir_entry].Name[i] = dirname[i]; // Set dir name
Dir[dir_entry].Attribute = attrib; // Set the attribute of the new directoryentry.
Dir[dir_entry].StartCluster = SubDirCluster; // copy the location of the first datacluster to the directoryentry.
Dir[dir_entry].DateTime = FileDateTime(&SystemTime); // set date/time
Dir[dir_entry].Size = 0; // the new createted file has no content yet.
if(SD_SUCCESS != SDC_PutSector(File->SectorInCache, File->Cache)) // write back to card
for(i = 0; i < 11; i++) dir[dir_entry].Name[i] = dirname[i]; // Set dir name
dir[dir_entry].Attribute = attrib; // Set the attribute of the new directoryentry.
dir[dir_entry].StartCluster = subdircluster; // copy the location of the first datacluster to the directoryentry.
dir[dir_entry].DateTime = FileDateTime(&SystemTime); // set date/time
dir[dir_entry].Size = 0; // the new createted file has no content yet.
if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache)) // write back to card
{
Fat16_Deinit();
return(retvalue);
}
File->FirstSectorOfFirstCluster = Fat16ClusterToSector(SubDirCluster); // Calculate absolute sectorposition of first datacluster.
File->FirstSectorOfCurrCluster = File->FirstSectorOfFirstCluster; // Start reading the file with the first sector of the first datacluster.
File->SectorOfCurrCluster = 0; // reset sector of cureen cluster
File->ByteOfCurrSector = 0; // reset the byte location within the current sector
File->Attribute = attrib; // set file attribute to dir attribute
File->Size = 0; // new file has no size
File->DirectorySector = curr_sector;
File->DirectoryIndex = dir_entry;
file->FirstSectorOfFirstCluster = Fat16ClusterToSector(subdircluster); // Calculate absolute sectorposition of first datacluster.
file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster; // Start reading the file with the first sector of the first datacluster.
file->SectorOfCurrCluster = 0; // reset sector of cureen cluster
file->ByteOfCurrSector = 0; // reset the byte location within the current sector
file->Attribute = attrib; // set file attribute to dir attribute
file->Size = 0; // new file has no size
file->DirectorySector = curr_sector;
file->DirectoryIndex = dir_entry;
if((attrib & ATTR_SUBDIRECTORY) == ATTR_SUBDIRECTORY) // if a new directory was created then initilize the data area
{
ClearCurrCluster(File); // fill cluster with zeros
File->SectorInCache = File->FirstSectorOfFirstCluster;
if(SD_SUCCESS != SDC_GetSector(File->SectorInCache, File->Cache))// read in the sector.
ClearCurrCluster(file); // fill cluster with zeros
file->SectorInCache = file->FirstSectorOfFirstCluster;
if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
{
Fat16_Deinit();
return(retvalue);
}
Dir = (DirEntry_t *)File->Cache;
dir = (DirEntry_t *)file->Cache;
// create direntry "." to current dir
Dir[0].Name[0] = 0x2E;
for(i = 1; i < 11; i++) Dir[0].Name[i] = ' ';
Dir[0].Attribute = ATTR_SUBDIRECTORY;
Dir[0].StartCluster = SubDirCluster;
Dir[0].DateTime = 0;
Dir[0].Size = 0;
dir[0].Name[0] = 0x2E;
for(i = 1; i < 11; i++) dir[0].Name[i] = ' ';
dir[0].Attribute = ATTR_SUBDIRECTORY;
dir[0].StartCluster = subdircluster;
dir[0].DateTime = 0;
dir[0].Size = 0;
// create direntry ".." to the upper dir
Dir[1].Name[0] = 0x2E;
Dir[1].Name[1] = 0x2E;
for(i = 2; i < 11; i++) Dir[1].Name[i] = ' ';
Dir[1].Attribute = ATTR_SUBDIRECTORY;
Dir[1].StartCluster = DirCluster;
Dir[1].DateTime = 0;
Dir[1].Size = 0;
if(SD_SUCCESS != SDC_PutSector(File->SectorInCache, File->Cache))// read in the sector.
dir[1].Name[0] = 0x2E;
dir[1].Name[1] = 0x2E;
for(i = 2; i < 11; i++) dir[1].Name[i] = ' ';
dir[1].Attribute = ATTR_SUBDIRECTORY;
dir[1].StartCluster = dircluster;
dir[1].DateTime = 0;
dir[1].Size = 0;
if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))// read in the sector.
{
Fat16_Deinit();
return(retvalue);
1137,9 → 1203,9
}while((dir_sector < max_dir_sector) && (!retvalue));
// if we are seaching in the data area and the file not found in this cluster so take next cluster.
if(!retvalue && ( Partition.FirstDataSector <= File->FirstSectorOfCurrCluster))
if(!retvalue && ( Partition.FirstDataSector <= file->FirstSectorOfCurrCluster))
{
end_of_directory_not_reached = GetNextCluster(File); // updates File->FirstSectorOfCurrCluster
end_of_directory_not_reached = GetNextCluster(file); // updates File->FirstSectorOfCurrCluster
}
}while((end_of_directory_not_reached) && (!retvalue));
// Perhaps we are at the end of the last cluster of a directory file an have no free direntry found.
1151,7 → 1217,7
}
 
/********************************************************************************************************************************************/
/* Function: FileExist(const u8* filename, u8 attribfilter, u8 attribmask, File_t *File); */
/* Function: FileExist(const s8* filename, u8 attribfilter, u8 attribmask, File_t *file); */
/* */
/* Description: This function looks for the specified filemincluding its subdirectories beginning */
/* in the rootdirectory of the drive. If the file is found the Filepointer properties are */
1159,23 → 1225,24
/* */
/* Returnvalue: 1 if file is found else 0. */
/********************************************************************************************************************************************/
u8 FileExist(const u8* filename, const u8 attribfilter, const u8 attribmask, File_t *File)
u8 FileExist(const s8* filename, const u8 attribfilter, const u8 attribmask, File_t *file)
{
u8 *path = 0, *subpath = 0;
s8* path = 0;
s8* subpath = 0;
u8 af, am, file_exist = 0;
u8 dirname[11];
s8 dirname[12];
 
// if incomming pointers are useless return immediatly
if ((filename == 0) || (File == 0) || (!Partition.IsValid)) return 0;
if ((filename == 0) || (file == NULL) || (!Partition.IsValid)) return 0;
 
// trace along the filepath
path = (u8*)filename; // start a the beginning of the filename string
File->DirectorySector = 0; // start at RootDirectory with file search
File->DirectoryIndex = 0;
path = (s8*)filename; // start a the beginning of the filename string
file->DirectorySector = 0; // start at RootDirectory with file search
file->DirectoryIndex = 0;
// as long as the file was not found and the remaining path is not empty
while((*path != 0) && !file_exist)
{ // separate dirname and subpath from filepath string
if((subpath = SeperateDirName(path, dirname)))
if(subpath != 0)
{
if(*subpath == 0)
{ // empty subpath indicates last element of dir chain
1187,7 → 1254,7
af = ATTR_SUBDIRECTORY;
am = ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL;
}
if(!DirectoryEntryExist(dirname, af, am, File))
if(!DirectoryEntryExist(dirname, af, am, file))
{
return (file_exist); // subdirectory does not exist
}
1211,7 → 1278,7
 
 
/********************************************************************************************************************************************/
/* Function: FileCreate(const u8* filename, u8 attrib, File_t *File); */
/* Function: FileCreate(const s8* filename, u8 attrib, File_t *file); */
/* */
/* Description: This function looks for the specified file including its subdirectories beginning */
/* in the rootdirectory of the partition. If the file is found the Filepointer properties are */
1219,24 → 1286,24
/* */
/* Returnvalue: 1 if file was created else 0. */
/********************************************************************************************************************************************/
u8 FileCreate(const u8* filename, const u8 attrib, File_t *File)
u8 FileCreate(const s8* filename, const u8 attrib, File_t *file)
{
u8 *path = 0;
u8 *subpath = 0;
s8 *path = 0;
s8 *subpath = 0;
u8 af, am, file_created = 0;
u8 dirname[11];
s8 dirname[12];
 
// if incomming pointers are useless return immediatly
if ((filename == 0) || (File == 0) || (!Partition.IsValid)) return 0;
if ((filename == NULL) || (file == NULL) || (!Partition.IsValid)) return 0;
 
// trace along the filepath
path = (u8*)filename; // start a the beginning of the filename string
File->DirectorySector = 0; // start at RootDirectory with file search
File->DirectoryIndex = 0;
path = (s8*)filename; // start a the beginning of the filename string
file->DirectorySector = 0; // start at RootDirectory with file search
file->DirectoryIndex = 0;
// as long as the file was not created and the remaining file path is not empty
while((*path != 0) && !file_created)
{ // separate dirname and subpath from filepath string
if((subpath = SeperateDirName(path, dirname)))
if(subpath != 0)
{
if(*subpath == 0)
{ // empty subpath indicates last element of dir chain
1248,10 → 1315,10
af = ATTR_SUBDIRECTORY;
am = ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL;
}
if(!DirectoryEntryExist(dirname, af, am, File)) // if subdir or file is not existent
if(!DirectoryEntryExist(dirname, af, am, file)) // if subdir or file is not existent
{ // try to create subdir or file
if(*subpath == 0) af = attrib; // if last element in dir chain take the given attribute
if(!CreateDirectoryEntry(dirname, af, File))
if(!CreateDirectoryEntry(dirname, af, file))
{ // could not be created
return(file_created);
}
1270,7 → 1337,7
 
 
/********************************************************************************************************************************************/
/* Function: File_t * fopen_(u8* filename, s8 mode); */
/* Function: File_t * fopen_(s8* filename, s8 mode); */
/* */
/* Description: This function looks for the specified file in the rootdirectory of the drive. If the file is found the number of the */
/* corrosponding filepointer is returned. Only modes 'r' (reading) and 'a' append are implemented yet. */
1277,68 → 1344,77
/* */
/* Returnvalue: The filepointer to the file or 0 if faild. */
/********************************************************************************************************************************************/
File_t * fopen_(const u8 *filename, const s8 mode)
File_t * fopen_(const s8 *filename, const s8 mode)
{
File_t *File = 0;
File_t *file = 0;
if((!Partition.IsValid) || (filename == 0)) return(File);
if((!Partition.IsValid) || (filename == 0)) return(file);
 
// Look for an unused filepointer in the file pointer list?
File = LockFilePointer();
file = LockFilePointer();
// if no unused file pointer was found return 0
if(File == 0) return(File);
if(file == NULL) return(file);
 
// now we have found a free filepointer and claimed it
// so let initiate its property values
File->FirstSectorOfFirstCluster = 0; // Sectorpointer to the first sector of the first datacluster of the file.
File->FirstSectorOfCurrCluster = 0; // Pointer to the cluster which is edited at the moment.
File->SectorOfCurrCluster = 0; // The sector which is edited at the moment (cluster_pointer + sector_index).
File->ByteOfCurrSector = 0; // The bytelocation within the current sector (cluster_pointer + sector_index + byte_index).
File->Mode = mode; // mode of fileoperation (read,write)
File->Size = 0; // the size of the opened file in bytes.
File->Position = 0; // pointer to a byte within the file 0 < fileposition < filesize
File->SectorInCache = 0; // the last sector read, wich is still in the sectorbuffer.
File->DirectorySector = 0; // the sectorposition where the directoryentry has been made.
File->DirectoryIndex = 0; // the index to the directoryentry within the specified sector.
File->Attribute = 0; // the attribute of the file opened.
file->FirstSectorOfFirstCluster = 0; // Sectorpointer to the first sector of the first datacluster of the file.
file->FirstSectorOfCurrCluster = 0; // Pointer to the cluster which is edited at the moment.
file->SectorOfCurrCluster = 0; // The sector which is edited at the moment (cluster_pointer + sector_index).
file->ByteOfCurrSector = 0; // The bytelocation within the current sector (cluster_pointer + sector_index + byte_index).
file->Mode = mode; // mode of fileoperation (read,write)
file->Size = 0; // the size of the opened file in bytes.
file->Position = 0; // pointer to a byte within the file 0 < fileposition < filesize
file->SectorInCache = 0; // the last sector read, wich is still in the sectorbuffer.
file->DirectorySector = 0; // the sectorposition where the directoryentry has been made.
file->DirectoryIndex = 0; // the index to the directoryentry within the specified sector.
file->Attribute = 0; // the attribute of the file opened.
 
// check if a real file (no directory) to the given filename exist
if(FileExist(filename, ATTR_NONE, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, File))
if(FileExist(filename, ATTR_NONE, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, file))
{ // file exist
switch(mode) // check mode
{
case 'a': // if mode is: append to file
if((File->Attribute & ATTR_READONLY) == ATTR_READONLY)
if((file->Attribute & ATTR_READONLY) == ATTR_READONLY)
{ // file is marked as readonly --> do not open this file
File->State = FSTATE_UNUSED; // release file pointer
File = 0;
fclose_(file);
file = NULL;
}
else
{ // file is not marked as read only --> goto end of file
fseek_(File, 0, SEEK_END); // point to the end of the file
fseek_(file, 0, SEEK_END); // point to the end of the file
}
break;
case 'w': // if mode is: write to file
if((File->Attribute & ATTR_READONLY) == ATTR_READONLY)
if((file->Attribute & ATTR_READONLY) == ATTR_READONLY)
{ // file is marked as readonly --> do not open this file
File->State = FSTATE_UNUSED; // release file pointer
File = 0;
fclose_(file);
file = NULL;
}
else
{ // file is not marked as read only --> goto start of file
fseek_(File, 0, SEEK_SET);
// free all clusters of that file
DeleteClusterChain(SectorToFat16Cluster(file->FirstSectorOfFirstCluster));
// mar an empy cluster as the last one and store the corresponding sector
file->FirstSectorOfFirstCluster = Fat16ClusterToSector(FindNextFreeCluster(file));
file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
file->SectorOfCurrCluster = 0;
file->ByteOfCurrSector = 0;
file->Size = 0;
file->Position = 0;
fseek_(file, 0, SEEK_SET);
}
break;
case 'r': // if mode is: read from to file
case 'r': // if mode is: read from file
// goto end of file
fseek_(File, 0, SEEK_SET);
fseek_(file, 0, SEEK_SET);
break;
default: // other modes are not supported
File->State = FSTATE_UNUSED; // release file pointer
File = 0;
fclose_(file);
file = NULL;
break;
}
return(File);
return(file);
}
else // file does not exist
{
1347,24 → 1423,24
case 'a':
case 'w': // if mode is write or append
// try to create the file
if(!FileCreate(filename, ATTR_ARCHIVE, File))
if(!FileCreate(filename, ATTR_ARCHIVE, file))
{ // if it could not be created
File->State = FSTATE_UNUSED; // release file pointer
File = 0;
fclose_(file);
file = NULL;
}
break;
case 'r': // else opend for 'r'
case 'r': // else opened for 'r'
default: // of unsupported mode
File->State = FSTATE_UNUSED; // release file pointer
File = 0;
fclose_(file);
file = NULL;
break;
}
return(File);
return(file);
}
// we should never come to this point
File->State = FSTATE_UNUSED; // release file pointer
File = 0;
return(File);
fclose_(file);
file = NULL;
return(file);
}
 
/****************************************************************************************************************************************************/
1374,35 → 1450,35
/* */
/* Returnvalue: 0 on success EOF on error */
/****************************************************************************************************************************************************/
s16 fflush_(File_t *File)
s16 fflush_(File_t *file)
{
DirEntry_t *Dir;
DirEntry_t *dir;
if((File == 0) || (!Partition.IsValid)) return (EOF);
if((file == NULL) || (!Partition.IsValid)) return (EOF);
switch(File->Mode)
switch(file->Mode)
{
case 'a':
case 'w':
if(File->ByteOfCurrSector > 0) // has data been added to the file?
if(file->ByteOfCurrSector > 0) // has data been added to the file?
{
if(SD_SUCCESS != SDC_PutSector(File->SectorInCache, File->Cache))// save the data still in the buffer
if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))// save the data still in the buffer
{
Fat16_Deinit();
return(EOF);
}
}
File->SectorInCache = File->DirectorySector;
if(SD_SUCCESS != SDC_GetSector(File->SectorInCache, File->Cache)) // read the directory entry for this file.
file->SectorInCache = file->DirectorySector;
if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache)) // read the directory entry for this file.
{
Fat16_Deinit();
return(EOF);
}
Dir = (DirEntry_t *)File->Cache;
Dir[File->DirectoryIndex].Size = File->Size; // update file size
Dir[File->DirectoryIndex].DateTime = FileDateTime(&SystemTime); // update date time
if(SD_SUCCESS != SDC_PutSector(File->SectorInCache, File->Cache)) // write back to sd-card
dir = (DirEntry_t *)file->Cache;
dir[file->DirectoryIndex].Size = file->Size; // update file size
dir[file->DirectoryIndex].DateTime = FileDateTime(&SystemTime); // update date time
if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache)) // write back to sd-card
{
Fat16_Deinit();
return(EOF);
1425,13 → 1501,13
/* */
/* Returnvalue: 0 on success EOF on error */
/****************************************************************************************************************************************/
s16 fclose_(File_t *File)
s16 fclose_(File_t *file)
{
s16 returnvalue = EOF;
 
if(File == 0) return(returnvalue);
returnvalue = fflush_(File);
UnlockFilePointer(File);
if(file == NULL) return(returnvalue);
returnvalue = fflush_(file);
UnlockFilePointer(file);
return(returnvalue);
}
 
1443,45 → 1519,45
/* */
/* Returnvalue: The function returns the character read from the specified memorylocation as u8 casted to s16 or EOF. */
/********************************************************************************************************************************************/
s16 fgetc_(File_t *File)
s16 fgetc_(File_t *file)
{
s16 c = EOF;
u32 curr_sector;
if( (!Partition.IsValid) || (File == 0)) return(c);
if( (!Partition.IsValid) || (file == NULL)) return(c);
// if the end of the file is not reached, get the next character.
if((0 < File->Size) && (File->Position < File->Size) )
if((0 < file->Size) && ((file->Position+1) < file->Size) )
{
curr_sector = File->FirstSectorOfCurrCluster; // calculate the sector of the next character to be read.
curr_sector += File->SectorOfCurrCluster;
curr_sector = file->FirstSectorOfCurrCluster; // calculate the sector of the next character to be read.
curr_sector += file->SectorOfCurrCluster;
if(File->SectorInCache != curr_sector)
if(file->SectorInCache != curr_sector)
{
File->SectorInCache = curr_sector;
if(SD_SUCCESS != SDC_GetSector(File->SectorInCache, File->Cache))
file->SectorInCache = curr_sector;
if(SD_SUCCESS != SDC_GetSector(file->SectorInCache,file->Cache))
{
Fat16_Deinit();
return(c);
}
}
c = (s16) File->Cache[File->ByteOfCurrSector];
File->Position++; // increment file position
File->ByteOfCurrSector++; // goto next byte in sector
if(File->ByteOfCurrSector >= BYTES_PER_SECTOR) // if end of sector
c = (s16) file->Cache[file->ByteOfCurrSector];
file->Position++; // increment file position
file->ByteOfCurrSector++; // goto next byte in sector
if(file->ByteOfCurrSector >= BYTES_PER_SECTOR) // if end of sector
{
File->ByteOfCurrSector = 0; // reset byte location
File->SectorOfCurrCluster++; // next sector
if(File->SectorOfCurrCluster >= Partition.SectorsPerCluster) // if end of cluster is reached, the next datacluster has to be searched in the FAT.
file->ByteOfCurrSector = 0; // reset byte location
file->SectorOfCurrCluster++; // next sector
if(file->SectorOfCurrCluster >= Partition.SectorsPerCluster) // if end of cluster is reached, the next datacluster has to be searched in the FAT.
{
if(GetNextCluster(File)) // Sets the clusterpointer of the file to the next datacluster.
if(GetNextCluster(file)) // Sets the clusterpointer of the file to the next datacluster.
{
File->SectorOfCurrCluster = 0; // start reading new cluster at first sector of the cluster.
file->SectorOfCurrCluster = 0; // start reading new cluster at first sector of the cluster.
}
else // the last cluster was allready reached
{
File->SectorOfCurrCluster--; // jump back to the last sector in the last cluster
File->ByteOfCurrSector = BYTES_PER_SECTOR; // set ByteOfCurrSector one byte over sector end
file->SectorOfCurrCluster--; // jump back to the last sector in the last cluster
file->ByteOfCurrSector = BYTES_PER_SECTOR; // set ByteOfCurrSector one byte over sector end
}
}
}
1490,7 → 1566,7
}
 
/********************************************************************************************************************************************/
/* Function: fputc_( const s8 c, File *File); */
/* Function: fputc_( const s8 c, File *file); */
/* */
/* Description: This function writes a byte to the specified file and takes care of writing the necessary FAT- Entries. */
/* next sector of the cluster is read. If the last sector of the cluster read the next cluster will be searched in FAT. */
1497,26 → 1573,26
/* */
/* Returnvalue: The function returns the character written to the stream or EOF on error. */
/********************************************************************************************************************************************/
s16 fputc_(const u8 c, File_t *File)
s16 fputc_(const s8 c, File_t *file)
{
u32 curr_sector = 0;
if((!Partition.IsValid) || (File == 0)) return(EOF);
if((!Partition.IsValid) || (file == NULL)) return(EOF);
 
// If file position equals to file size, then the end of file has reached.
// In this chase it has to be checked that the ByteOfCurrSector is BYTES_PER_SECTOR
// and a new cluster should be appended.
if((File->Position >= File->Size) && (File->ByteOfCurrSector >= BYTES_PER_SECTOR))
if((file->Position >= file->Size) && (file->ByteOfCurrSector >= BYTES_PER_SECTOR))
{
if(!AppendCluster(File)) return(EOF);
if(!AppendCluster(file)) return(EOF);
}
 
curr_sector = File->FirstSectorOfCurrCluster;
curr_sector += File->SectorOfCurrCluster;
if(File->SectorInCache != curr_sector)
curr_sector = file->FirstSectorOfCurrCluster;
curr_sector += file->SectorOfCurrCluster;
if(file->SectorInCache != curr_sector)
{
File->SectorInCache = curr_sector;
if(SD_SUCCESS != SDC_GetSector(File->SectorInCache, File->Cache))
file->SectorInCache = curr_sector;
if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))
{
Fat16_Deinit();
return(EOF);
1523,33 → 1599,33
}
}
 
File->Cache[File->ByteOfCurrSector] = c; // write databyte into the buffer. The byte will be written to the device at once
if(File->Size == File->Position) File->Size++; // a character has been written to the file so the size is incremented only when the character has been added at the end of the file.
File->Position++; // the actual positon within the file.
File->ByteOfCurrSector++; // goto next byte in sector
if(File->ByteOfCurrSector >= BYTES_PER_SECTOR) // if the end of this sector is reached yet
file->Cache[file->ByteOfCurrSector] = (u8)c; // write databyte into the buffer. The byte will be written to the device at once
if(file->Size == file->Position) file->Size++; // a character has been written to the file so the size is incremented only when the character has been added at the end of the file.
file->Position++; // the actual positon within the file.
file->ByteOfCurrSector++; // goto next byte in sector
if(file->ByteOfCurrSector >= BYTES_PER_SECTOR) // if the end of this sector is reached yet
{ // save the sector to the sd-card
if(SD_SUCCESS != SDC_PutSector(File->SectorInCache, File->Cache))
if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
{
Fat16_Deinit();
return(EOF);
}
File->ByteOfCurrSector = 0; // reset byte location
File->SectorOfCurrCluster++; // next sector
if(File->SectorOfCurrCluster >= Partition.SectorsPerCluster)// if end of cluster is reached, the next datacluster has to be searched in the FAT.
file->ByteOfCurrSector = 0; // reset byte location
file->SectorOfCurrCluster++; // next sector
if(file->SectorOfCurrCluster >= Partition.SectorsPerCluster)// if end of cluster is reached, the next datacluster has to be searched in the FAT.
{
if(!GetNextCluster(File)) // Sets the clusterpointer of the file to the next datacluster.
if(!GetNextCluster(file)) // Sets the clusterpointer of the file to the next datacluster.
{ // if current cluster was the last cluster of the file
if(!AppendCluster(File)) // append a new and free cluster at the end of the file.
if(!AppendCluster(file)) // append a new and free cluster at the end of the file.
{
File->SectorOfCurrCluster--; // jump back to last sector of last cluster
File->ByteOfCurrSector = BYTES_PER_SECTOR; // set byte location to 1 byte over sector len
file->SectorOfCurrCluster--; // jump back to last sector of last cluster
file->ByteOfCurrSector = BYTES_PER_SECTOR; // set byte location to 1 byte over sector len
return(EOF);
}
}
else // next cluster
{
File->SectorOfCurrCluster = 0; // start reading new cluster at first sector of the cluster.
file->SectorOfCurrCluster = 0; // start reading new cluster at first sector of the cluster.
}
}
}
1565,7 → 1641,7
/* */
/* Returnvalue: The function returns the number of objects (not bytes) read from the file. */
/****************************************************************************************************************************************/
u32 fread_(void *buffer, u32 size, u32 count, File_t *File)
u32 fread_(void *buffer, u32 size, u32 count, File_t *file)
{
u32 object_cnt = 0; // count the number of objects read from the file.
u32 object_size = 0; // count the number of bytes read from the actual object.
1573,7 → 1649,7
u8 success = 1; // no error occured during read operation to the file.
s16 c;
 
if((!Partition.IsValid) || (File == 0) || (buffer == 0)) return(0);
if((!Partition.IsValid) || (file == NULL) || (buffer == NULL)) return(0);
 
pbuff = (u8 *) buffer; // cast the void pointer to an u8 *
1582,7 → 1658,7
object_size = size;
while((size > 0) && success)
{
c = fgetc_(File);
c = fgetc_(file);
if(c != EOF)
{
*pbuff = (u8)c; // read a byte from the buffer to the opened file.
1608,7 → 1684,7
/* */
/* Returnvalue: The function returns the number of objects (not bytes) read from the file. */
/****************************************************************************************************************************************/
u32 fwrite_(void *buffer, u32 size, u32 count, File_t *File)
u32 fwrite_(void *buffer, u32 size, u32 count, File_t *file)
{
u32 object_cnt = 0; // count the number of objects written to the file.
u32 object_size = 0; // count the number of bytes written from the actual object.
1616,7 → 1692,7
u8 success = 1; // no error occured during write operation to the file.
s16 c;
 
if((!Partition.IsValid) || (File == 0) || (buffer == 0)) return(0);
if((!Partition.IsValid) || (file == NULL) || (buffer == NULL)) return(0);
 
pbuff = (u8 *) buffer; // cast the void pointer to an u8 *
1625,7 → 1701,7
object_size = size;
while((size > 0) && success)
{
c = fputc_(*pbuff, File); // write a byte from the buffer to the opened file.
c = fputc_(*pbuff, file); // write a byte from the buffer to the opened file.
if(c != EOF)
{
pbuff++;
1644,22 → 1720,22
 
 
/****************************************************************************************************************************************/
/* Function: fputs_(const u8 *string, File_t *File); */
/* Function: fputs_(const s8 *string, File_t *File); */
/* */
/* Description: This function writes a string to the specified file. */
/* */
/* Returnvalue: The function returns a no negative value or EOF on error. */
/****************************************************************************************************************************************/
s16 fputs_(const u8 *string, File_t *File)
s16 fputs_(const s8 *string, File_t *file)
{
u8 i=0;
s16 c = 0;
if((!Partition.IsValid) || (File == 0) || (string == 0)) return(0);
if((!Partition.IsValid) || (file == NULL) || (string == NULL)) return(0);
 
while((string[i] != 0)&& (c != EOF))
{
c = fputc_(string[i], File);
c = fputc_(string[i], file);
i++;
}
return(c);
1666,22 → 1742,22
}
 
/****************************************************************************************************************************************/
/* Function: fgets_(u8 *, s16 , File_t *); */
/* Function: fgets_(s8 *, s16 , File_t *); */
/* */
/* Description: This function reads a string from the file to the specifies string. */
/* */
/* Returnvalue: A pointer to the string read from the file or 0 on error. */
/****************************************************************************************************************************************/
u8 * fgets_(u8 *string, s16 length, File_t *File)
u8 * fgets_(s8 *string, s16 length, File_t *file)
{
u8 *pbuff;
s16 c = 0;
if((!Partition.IsValid) || (File == 0) || (string == 0) || (length = 0)) return (0);
if((!Partition.IsValid) || (file == NULL) || (string == NULL) || (length = 0)) return (0);
pbuff = string;
while(length > 1) // read the count-1 characters from the file to the string.
{
c = fgetc_(File); // read a character from the opened file.
c = fgetc_(file); // read a character from the opened file.
switch(c)
{
case 0x0A:
1702,19 → 1778,39
}
 
/****************************************************************************************************************************************/
/* Function: fexit_(const u8*); */
/* Function: fexist_(const u8*); */
/* */
/* Description: This function checks if a file already exist. */
/* */
/* Returnvalue: 1 if the file exist else 0. */
/****************************************************************************************************************************************/
u8 fexit_(const u8* filename)
u8 fexist_(const s8* filename)
{
u8 exist = 0;
File_t *File = 0;
File = LockFilePointer();
exist = FileExist(filename, ATTR_NONE, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, File);
UnlockFilePointer(File);
File_t *file = 0;
file = LockFilePointer();
exist = FileExist(filename, ATTR_NONE, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, file);
UnlockFilePointer(file);
return(exist);
}
 
/****************************************************************************************************************************************/
/* Function: feof_(File_t *File); */
/* */
/* Description: This function checks wether the end of the file has been reached. */
/* */
/* Returnvalue: 0 if the end of the file was not reached otherwise 1. */
/****************************************************************************************************************************************/
u8 feof_(File_t *file)
{
if(((file->Position)+1) < (file->Size))
{
return(0);
}
else
{
return(1);
}
}
 
 
/branches/V0.1 killagreg/fat16.h
44,22 → 44,24
//
//________________________________________________________________________________________________________________________________________
 
extern u8 Fat16_Init(void);
extern u8 Fat16_Deinit(void);
u8 Fat16_Init(void);
u8 Fat16_Deinit(void);
extern File_t * fopen_(const u8 *filename, const s8 mode);
extern s16 fclose_(File_t *File);
extern u8 fexist_(const u8 *filename);
extern s16 fflush_(File_t *File);
extern s16 fseek_(File_t *File, s32 offset, s16 origin);
extern s16 fgetc_(File_t *File);
extern s16 fputc_(u8 c, File_t *File);
extern u32 fread_(void *buffer, u32 size, u32 count, File_t *File);
extern u32 fwrite_(void *buffer, u32 size, u32 count, File_t *File);
extern s16 fputs_(const u8 *string, File_t *File);
extern u8 * fgets_(u8 *string, s16 length, File_t *File);
File_t *fopen_(const s8 *filename, const s8 mode);
s16 fclose_(File_t *file);
u8 fexist_(const s8 *filename);
s16 fflush_(File_t *file);
s16 fseek_(File_t *file, s32 offset, s16 origin);
s16 fgetc_(File_t *file);
s16 fputc_(s8 c, File_t *file);
u32 fread_(void *buffer, u32 size, u32 count, File_t *file);
u32 fwrite_(void *buffer, u32 size, u32 count, File_t *file);
s16 fputs_(const s8 *string, File_t *file);
u8 * fgets_(s8 *string, s16 length, File_t *file);
u8 feof_(File_t *file);
 
 
 
#endif //_FAT16_H
 
 
/branches/V0.1 killagreg/i2c.c
56,122 → 56,198
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#include "91x_lib.h"
#include "i2c.h"
#include "uart.h"
#include "uart1.h"
#include "timer.h"
#include "main.h"
#include "led.h"
 
 
volatile I2C_State_t I2C_State;
 
// rxbuffer
u8 I2C_RxBufferSize;
u8 *I2C_RxBuffer;
u8 Rx_Idx = 0;
volatile u8 I2C_RxBufferSize;
volatile u8 *I2C_RxBuffer;
volatile u8 Rx_Idx = 0;
// txbuffer
u8 I2C_TxBufferSize;
u8 *I2C_TxBuffer;
u8 Tx_Idx = 0;
volatile u8 I2C_TxBufferSize;
volatile u8 *I2C_TxBuffer;
volatile u8 Tx_Idx = 0;
 
u8 I2C_Direction;
u8 I2C_Command;
volatile u8 I2C_Direction;
volatile u8 I2C_Command;
 
I2C_Heading_t I2C_Heading;
I2C_WriteAttitude_t I2C_WriteAttitude;
I2C_Mag_t I2C_Mag;
I2C_EEPROM_t I2C_ReadEEPROM, I2C_WriteEEPROM;
I2C_Version_t I2C_Version;
I2C_WriteCal_t I2C_WriteCal;
volatile I2C_Heading_t I2C_Heading;
volatile I2C_WriteAttitude_t I2C_WriteAttitude;
volatile I2C_Mag_t I2C_Mag;
volatile I2C_EEPROM_t I2C_ReadEEPROM, I2C_WriteEEPROM;
volatile I2C_Version_t I2C_Version;
volatile I2C_WriteCal_t I2C_WriteCal;
 
u8 CompassUpdateActiv = 0;
u8 CompassCalState = 0;
 
volatile u8 I2C_ReadRequest = 0;
volatile u32 I2C1_Timeout = 0;
 
 
 
 
//--------------------------------------------------------------
void I2C1_Init(void)
{
I2C_InitTypeDef I2C_Struct;
GPIO_InitTypeDef GPIO_Struct;
GPIO_InitTypeDef GPIO_InitStructure;
SerialPutString("I2C init...");
SerialPutString("\r\n I2C init...");
SCU_APBPeriphClockConfig(__I2C1,ENABLE);
I2C_DeInit(I2C1);
// configure P2.2->I2C1_CLKOUT and P2.3->I2C1_DOUT
GPIO_Struct.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;
GPIO_Struct.GPIO_Type = GPIO_Type_OpenCollector;
GPIO_Struct.GPIO_IPConnected = GPIO_IPConnected_Enable;
GPIO_Struct.GPIO_Alternate=GPIO_OutputAlt2; //I2C1_CLKOUT, I2C1_DOUT
GPIO_Init(GPIO2, &GPIO_Struct);
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;
GPIO_InitStructure.GPIO_Type = GPIO_Type_OpenCollector;
GPIO_InitStructure.GPIO_IPConnected = GPIO_IPConnected_Enable;
GPIO_InitStructure.GPIO_Alternate=GPIO_OutputAlt2; //I2C1_CLKOUT, I2C1_DOUT
GPIO_Init(GPIO2, &GPIO_InitStructure);
 
I2C_StructInit(&I2C_Struct);
I2C_Struct.I2C_GeneralCall = I2C_GeneralCall_Disable;
I2C_Struct.I2C_Ack = I2C_Ack_Enable;
I2C_Struct.I2C_CLKSpeed = 20000;
I2C_Struct.I2C_OwnAddress = I2C_SLAVE_ADDRESS;
I2C_Struct.I2C_OwnAddress = 0x00; //??
I2C_Init(I2C1, &I2C_Struct);
I2C_Cmd(I2C1, ENABLE);
I2C_ITConfig(I2C1, ENABLE);
VIC_Config(I2C1_ITLine, VIC_IRQ , 8);
VIC_Config(I2C1_ITLine, VIC_IRQ , 0);
VIC_ITCmd(I2C1_ITLine, ENABLE);
 
I2C1_Timeout = SetDelay(1000);
I2C_Heading.Heading = -1;
SerialPutString("ok\n\r");
I2C_State = I2C_IDLE;
SerialPutString("ok");
}
 
 
//--------------------------------------------------------------
void I2C1_Deinit(void)
{
SerialPutString("\r\n I2C deinit...");
I2C_GenerateStart(I2C1, DISABLE);
I2C_GenerateSTOP(I2C1, ENABLE);
VIC_ITCmd(I2C1_ITLine, DISABLE);
I2C_ITConfig(I2C1, DISABLE);
I2C_Cmd(I2C1, DISABLE);
I2C_DeInit(I2C1);
SCU_APBPeriphClockConfig(__I2C1,DISABLE);
 
I2C_State = I2C_UNDEF;
I2C1_Timeout = 0;
I2C_Heading.Heading = 0;
SerialPutString("ok");
}
 
 
//--------------------------------------------------------------
void I2C1_IRQHandler(void)
{
switch (I2C_GetLastEvent(I2C1))
{
// the start condition was initiated on the bus
case I2C_EVENT_MASTER_MODE_SELECT: // EV5
// reset TX/RX buffer indices
Tx_Idx = 0;
Rx_Idx = 0;
// update current bus state variable
switch(I2C_Direction)
{
case I2C_MODE_TRANSMITTER:
I2C_State = I2C_TX_PROGRESS;
break;
 
case I2C_MODE_RECEIVER:
I2C_State = I2C_RX_PROGRESS;
break;
 
default:
I2C_State = I2C_UNDEF;
break;
}
// send address/direction byte on the bus
I2C_Send7bitAddress(I2C1, I2C_SLAVE_ADDRESS, I2C_Direction);
// reset timeout
I2C1_Timeout = SetDelay(500); // after 500 ms of inactivity the I2C1 bus will be reset
break;
 
// tha address byte was send
case I2C_EVENT_MASTER_MODE_SELECTED: // EV6
// Clear EV6 by set again the PE bit
I2C1->CR |= 0x20;
if (I2C_Direction == I2C_MODE_TRANSMITTER)
{
I2C_SendData(I2C1, I2C_Command); //EV8 just after EV6
}
switch(I2C_State)
{
case I2C_TX_PROGRESS:
// send command 1st data byte (allways the command id)
I2C_SendData(I2C1, I2C_Command);
break;
 
case I2C_RX_PROGRESS:
// before the last byte is received the master should disable
// the acknowledge bit to signal the slave that
// no more bytes
// the ACK is disabled here only if 1 byte is expected
if(I2C_RxBufferSize == 1) I2C_AcknowledgeConfig(I2C1, DISABLE);
break;
 
default:
// should never happen
I2C_GenerateSTOP (I2C1, ENABLE);
I2C_State = I2C_IDLE;
break;
}
break;
 
case I2C_EVENT_MASTER_BYTE_TRANSMITTED: // EV8
if ( Tx_Idx >= I2C_TxBufferSize )
// the master has transmitted a byte to the slave
case I2C_EVENT_MASTER_BYTE_TRANSMITTED: // EV8
// if all bytes are transmitted
if ( Tx_Idx >= I2C_TxBufferSize ) // all bytes transmitted
{
I2C_GenerateSTOP (I2C1, ENABLE);
Tx_Idx = 0;
if (I2C_RxBufferSize > 0) // is answer expected?
// generate a STOP condition on the bus
I2C_GenerateSTOP (I2C1, ENABLE); // generate stop condition to free the bus
if (I2C_RxBufferSize > 0) // is any answer byte expected?
{
I2C_ReadRequest = 1;
TimerI2CReadDelay = SetDelay(10);
I2C_State = I2C_RX_PENDING; // data can be read back
TimerI2CReadDelay = SetDelay(10); // start master receiver sequence in 10 ms
}
else I2C_State = I2C_IDLE; // ready for new actions
}
else
else // some bytes have to be transmitted
{
I2C_SendData(I2C1, I2C_TxBuffer[Tx_Idx]);
I2C_SendData(I2C1, I2C_TxBuffer[Tx_Idx]); // send next byte
Tx_Idx++;
}
break;
case I2C_EVENT_MASTER_BYTE_RECEIVED: // EV7
// the master has received a byte from the slave
case I2C_EVENT_MASTER_BYTE_RECEIVED: // EV7
DebugOut.Analog[16]++;
// before the last byte
if ( (Rx_Idx + 2) >= I2C_RxBufferSize )
{ // disable the ACK to signal the slave that the next received byte is the last one
I2C_AcknowledgeConfig (I2C1, DISABLE);
}
// if the last byte was received
if ( (Rx_Idx + 1) >= I2C_RxBufferSize )
{
// generate a STOP condition on the bus
I2C_GenerateSTOP(I2C1, ENABLE);
I2C_State = I2C_IDLE;
LED_GRN_TOGGLE;
}
// as long as there is some space in the rx-buffer
if (Rx_Idx < I2C_RxBufferSize)
{
{ // copy received byte from the data register to the rx-buffer
I2C_RxBuffer[Rx_Idx] = I2C_ReceiveData(I2C1);
}
else I2C_ReceiveData(I2C1);
Rx_Idx++;
if ( Rx_Idx == I2C_RxBufferSize-2 )
{
I2C_AcknowledgeConfig (I2C1, DISABLE);
}
if ( Rx_Idx == I2C_RxBufferSize -1 )
{
I2C_GenerateSTOP(I2C1, ENABLE);
if (I2C_Command == I2C_CMD_READ_HEADING) CompassUpdateActiv = 0;
}
else I2C_ReceiveData(I2C1); // just read the data register
Rx_Idx++; // set index to next byte
break;
 
default:
179,10 → 255,16
}
}
//----------------------------------------------------------------
void SendI2C_Command(u8 command)
void I2C1_SendCommand(u8 command)
{
I2C_Command = command;
//I2C_GenerateSTOP(I2C1, ENABLE);
// If I2C transmission is in progress
if (I2C_State != I2C_IDLE) return; // return
// disable I2C IRQ to avoid read/write access to the tx/rx buffer pointers during
// update of that buffer pointers and length
I2C_ITConfig(I2C1, DISABLE);
// update current command id
I2C_Command = command;
// set pointers to data area with respect to the command id
switch (command)
{
case I2C_CMD_VERSION:
213,7 → 295,6
I2C_TxBufferSize = 0;
break;
case I2C_CMD_READ_HEADING:
CompassUpdateActiv = 1;
I2C_RxBuffer = (u8 *)&I2C_Heading;
I2C_RxBufferSize = sizeof(I2C_Heading);
I2C_TxBuffer = (u8 *)&I2C_WriteAttitude;
221,14 → 302,28
break;
 
}
if (I2C_RxBufferSize > 0)
{
I2C_RxBufferSize++;
if (I2C_RxBufferSize < 3) I2C_RxBufferSize = 3;
}
I2C_AcknowledgeConfig (I2C1, ENABLE);
// enable I2C IRQ again
I2C_ITConfig(I2C1, ENABLE);
// set direction to master transmitter
I2C_Direction = I2C_MODE_TRANSMITTER;
// enable acknowledge
I2C_AcknowledgeConfig(I2C1, ENABLE);
// initiale start condition on the bus
I2C_GenerateStart(I2C1, ENABLE);
// to be continued in the I2C1_IRQHandler() above
}
 
void I2C1_ReadAnswer(void)
{
// only if the bus state is matching
if (I2C_State == I2C_RX_PENDING)
{
// set direction to master receiver
I2C_Direction = I2C_MODE_RECEIVER;
// enable acknowledge
I2C_AcknowledgeConfig(I2C1, ENABLE);
// initiale start condition on the bus
I2C_GenerateStart(I2C1, ENABLE);
// to be continued in the I2C1_IRQHandler() above
}
}
/branches/V0.1 killagreg/i2c.h
54,22 → 54,33
u16 Heading;
} __attribute__((packed)) I2C_Heading_t;
 
typedef enum
{
I2C_UNDEF,
I2C_IDLE,
I2C_TX_PROGRESS,
I2C_RX_PENDING,
I2C_RX_PROGRESS,
} I2C_State_t;
 
extern u8 Tx_Idx, Rx_Idx, I2C_Direction;
extern u8 CompassCalState;
extern volatile I2C_State_t I2C_State;
extern volatile u8 I2C_Direction;
extern volatile u32 I2C1_Timeout;
 
extern I2C_Heading_t I2C_Heading;
extern I2C_WriteAttitude_t I2C_WriteAttitude;
extern I2C_Mag_t I2C_Mag;
extern I2C_EEPROM_t I2C_ReadEEPROM, I2C_WriteEEPROM;
extern I2C_Version_t I2C_Version;
extern I2C_WriteCal_t I2C_WriteCal;
extern volatile I2C_Heading_t I2C_Heading;
extern volatile I2C_WriteAttitude_t I2C_WriteAttitude;
extern volatile I2C_Mag_t I2C_Mag;
extern volatile I2C_EEPROM_t I2C_ReadEEPROM, I2C_WriteEEPROM;
extern volatile I2C_Version_t I2C_Version;
extern volatile I2C_WriteCal_t I2C_WriteCal;
 
extern void I2C1_Init(void);
extern void SendI2C_Command(u8 command);
extern u8 CompassUpdateActiv;
extern volatile u8 I2C_ReadRequest;
extern u8 CompassCalState;
 
 
void I2C1_Init(void);
void I2C1_Deinit(void);
void I2C1_SendCommand(u8 command);
void I2C1_ReadAnswer(void);
 
#endif // I2C_H
 
/branches/V0.1 killagreg/interrupt.c
57,6 → 57,9
//#include "main.h"
#include "91x_lib.h"
#include "usb_lib.h"
#include "fat16.h"
#include "main.h"
#include "uart1.h"
#define global extern /* to declare external variables and functions */
 
extern void USB_Istr(void);
69,29 → 72,65
 
void Dummy_Handler(void)
{
VIC0->VAR = 0xFF;
VIC1->VAR = 0XFF;
VIC0->VAR = 0xFF;
VIC1->VAR = 0xFF;
}
 
/* avoid the surprising reset-like behaviour by spurious interrupts */
void Interrupt_Init(void)
{
VIC0->DVAR = (u32)Dummy_Handler;
VIC1->DVAR = (u32)Dummy_Handler;
}
 
/*******************************************************************************
* Function Name : SWI_Handler
* Description : This function handles SW exception.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void SWI_Handler (void)
{
}
 
/*******************************************************************************
* Function Name : Abort_Handler
* Description : This function handles data abort exception.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void Abort_Handler (void)
{
SerialPutString("\r\nAbort Handler");
while(1)
{
// infinite loop
}
}
 
/*******************************************************************************
* Function Name : Undefined_Handler
* Description : This function handles undefined instruction exception.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void Undefined_Handler (void)
{
SerialPutString("\r\nUndefined Handler");
while(1)
{
// infinite loop
}
}
 
/*******************************************************************************
* Function Name : FIQ_Handler
* Description : This function handles FIQ exception.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void FIQ_Handler (void)
{
}
101,6 → 140,11
*******************************************************************************/
void Prefetch_Handler(void)
{
SerialPutString("\r\nPrefetch Handler");
while(1)
{
// infinite loop
}
}
/*******************************************************************************
* Function Name : WDG_IRQHandler
108,6 → 152,12
*******************************************************************************/
void WDG_IRQHandler(void)
{
/*write your handler here*/
/* ... */
/*write any value to VIC0 VAR*/
VIC0->VAR = 0xFF;
}
/*******************************************************************************
* Function Name : SW_IRQHandler
115,6 → 165,12
*******************************************************************************/
void SW_IRQHandler(void)
{
/*write your handler here*/
/* ... */
/*write any value to VIC0 VAR*/
VIC0->VAR = 0xFF;
}
/*******************************************************************************
* Function Name : ARMRX_IRQHandler
122,6 → 178,12
*******************************************************************************/
void ARMRX_IRQHandler(void)
{
/*write your handler here*/
/* ... */
/*write any value to VIC0 VAR*/
VIC0->VAR = 0xFF;
}
/*******************************************************************************
* Function Name : ARMTX_IRQHandler
129,6 → 191,12
*******************************************************************************/
void ARMTX_IRQHandler(void)
{
/*write your handler here*/
/* ... */
/*write any value to VIC0 VAR*/
VIC0->VAR = 0xFF;
}
/*******************************************************************************
* Function Name : TIM0_IRQHandler
136,14 → 204,24
*******************************************************************************/
void TIM0_IRQHandler(void)
{
/*write your handler here*/
/* ... */
/*write any value to VIC0 VAR*/
VIC0->VAR = 0xFF;
}
/*******************************************************************************
* Function Name : TIM1_IRQHandler
* Description : This function handles the TIM1 interrupt request
*******************************************************************************/
//void TIM1_IRQHandler(void)
//{
//}
/*
void TIM1_IRQHandler(void)
{
// write any value to VIC0 VAR //
VIC0->VAR = 0xFF;
}
*/
/*******************************************************************************
* Function Name : TIM2_IRQHandler
* Description : This function handles the TIM2 interrupt request
150,6 → 228,12
*******************************************************************************/
void TIM2_IRQHandler(void)
{
/*write your handler here*/
/* ... */
/*write any value to VIC0 VAR*/
VIC0->VAR = 0xFF;
}
/*******************************************************************************
* Function Name : TIM3_IRQHandler
157,6 → 241,12
*******************************************************************************/
void TIM3_IRQHandler(void)
{
/*write your handler here*/
/* ... */
/*write any value to VIC0 VAR*/
VIC0->VAR = 0xFF;
}
/*******************************************************************************
* Function Name : USBHP_IRQHandler
164,7 → 254,9
*******************************************************************************/
void USBHP_IRQHandler(void)
{
CTR_HP();
CTR_HP();
/*write any value to VIC0 VAR*/
VIC0->VAR = 0xFF;
}
/*******************************************************************************
* Function Name : USBLP_IRQHandler
172,7 → 264,8
*******************************************************************************/
void USBLP_IRQHandler(void)
{
USB_Istr();
USB_Istr(); /*write any value to VIC0 VAR*/
VIC0->VAR = 0xFF;
}
/*******************************************************************************
* Function Name : SCU_IRQHandler
180,6 → 273,12
*******************************************************************************/
void SCU_IRQHandler(void)
{
/*write your handler here*/
/* ... */
/*write any value to VIC0 VAR*/
VIC0->VAR = 0xFF;
}
/*******************************************************************************
* Function Name : ENET_IRQHandler
187,6 → 286,12
*******************************************************************************/
void ENET_IRQHandler(void)
{
/*write your handler here*/
/* ... */
/*write any value to VIC0 VAR*/
VIC0->VAR = 0xFF;
}
/*******************************************************************************
* Function Name : DMA_IRQHandler
194,6 → 299,12
*******************************************************************************/
void DMA_IRQHandler(void)
{
/*write your handler here*/
/* ... */
/*write any value to VIC0 VAR*/
VIC0->VAR = 0xFF;
}
/*******************************************************************************
* Function Name : CAN_IRQHandler
201,6 → 312,12
*******************************************************************************/
void CAN_IRQHandler(void)
{
/*write your handler here*/
/* ... */
/*write any value to VIC0 VAR*/
VIC0->VAR = 0xFF;
}
/*******************************************************************************
* Function Name : MC_IRQHandler
208,6 → 325,12
*******************************************************************************/
void MC_IRQHandler(void)
{
/*write your handler here*/
/* ... */
/*write any value to VIC0 VAR*/
VIC0->VAR = 0xFF;
}
/*******************************************************************************
* Function Name : ADC_IRQHandler
215,6 → 338,12
*******************************************************************************/
void ADC_IRQHandler(void)
{
/*write your handler here*/
/* ... */
/*write any value to VIC0 VAR*/
VIC0->VAR = 0xFF;
}
/*******************************************************************************
* Function Name : UART0_IRQHandler
227,15 → 356,9
* Function Name : UART1_IRQHandler
* Description : This function handles the UART1 interrupt request
*******************************************************************************/
//void UART1_IRQHandler(void) __attribute__ ((interrupt ("IRQ")));
/*void UART1_IRQHandler(void)
{
UART1->DR = UART1->DR;
 
UART_ClearITPendingBit(UART1, UART_IT_Receive);
}
*/
{
} */
/*******************************************************************************
* Function Name : UART2_IRQHandler
* Description : This function handles the UART2 interrupt request
303,9 → 426,19
* Function Name : EXTIT1_IRQHandler
* Description : This function handles the EXTIT1 interrupt request
*******************************************************************************/
/*void EXTIT1_IRQHandler(void)
void EXTIT1_IRQHandler(void)
{
}*/
VIC_ITCmd(EXTIT1_ITLine, DISABLE);
if(WIU_GetITStatus(WIU_Line11) != RESET)
{
BeepTime = 100;
Fat16_Init(); // initialize sd-card file system.
 
WIU_ClearFlag(WIU_Line1);
WIU_ClearITPendingBit(WIU_Line11);
}
VIC_ITCmd(EXTIT1_ITLine, ENABLE);
}
/*******************************************************************************
* Function Name : EXTIT2_IRQHandler
* Description : This function handles the EXTIT2 interrupt request
/branches/V0.1 killagreg/kml.c
0,0 → 1,382
/*#######################################################################################*/
/* !!! THIS IS NOT FREE SOFTWARE !!! */
/*#######################################################################################*/
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Copyright (c) 2008 Ingo Busker, Holger Buss
// + Nur für den privaten Gebrauch
// + FOR NON COMMERCIAL USE ONLY
// + 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 (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 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 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 permitted
// + 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
// + * If sources or documentations are redistributet on other webpages, out webpage (http://www.MikroKopter.de) must be
// + clearly linked as origin
// + * PORTING this software (or part of it) 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.
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#include <stdlib.h>
#include <stdio.h>
#include "91x_lib.h"
#include "kml.h"
#include "kml_header.h"
 
 
//________________________________________________________________________________________________________________________________________
// Module name: kml.c
// Compiler used: avr-gcc 3.4.5
// Last Modifikation: 20.07.2008
// Version: 1.02
// Authors: Stephan Busker
// Description: Source files to write gps-coordinates to a file in the kml (keyhole markup language) fileformat
// Copyright (C) 2007 Stephan Busker
//........................................................................................................................................
// Functions: extern u8 KML_LoggGPSCoordinates(struct str_gps_nav_data , KML_Document_t *); // intializes the kml-document with standard filename and adds points to the file
// extern u8 KML_DocumentInit(KML_Document_t *doc) // initializes the kml-document to resetvalues.
// extern u8 KML_DocumentOpen(s8 *, KML_Document_t *); // opens a new kml document. A filename can be specified.
// extern u8 KML_DocumentClose(KML_Document_t *doc); // closes an open document
// extern u8 KML_PlaceMarkOpen(s8 *name, KML_Document_t *); // opens a new placemark within the specified document
// extern u8 KML_PlaceMarkClose( KML_Document_t *); // Closes the placemark
// extern u8 KML_LineStringBegin(KML_Document_t *); // begins a new line within the actual placemark
// extern u8 KML_LineStringEnd(KML_Document_t *doc); // ends the actual linestring
// extern u8 KML_LineStringAddPoint(struct str_gps_nav_data, KML_Document_t *); // adds a new point (gps-coordinates) to the actual linestring
//........................................................................................................................................
// ext. functions:
//
//........................................................................................................................................
//
// URL: www.Mikro-Control.de
// mailto: stephan.busker@mikro-control.de
//________________________________________________________________________________________________________________________________________
 
 
 
//________________________________________________________________________________________________________________________________________
// Function: KML_DocumentInit(KML_Document_t *)
//
// Description: This function initializes the kml-document for further use.
//
//
// Returnvalue: '1' if document was initialized
//________________________________________________________________________________________________________________________________________
 
u8 KML_DocumentInit(KML_Document_t *doc)
{
doc->name[0] = 0; // name of the document
doc->state = DOC_CLOSED; // state of the kml-document
doc->file = NULL;
doc->place.name[0]=0;
doc->place.description[0]=0;
return(1);
}
 
//________________________________________________________________________________________________________________________________________
// Function: KML_Document_Open(void);
//
// Description: This function opens a new KML- document with the specified name and creates the document header within the file.
//
//
// Returnvalue: '1' if the KML- file could be created.
//________________________________________________________________________________________________________________________________________
 
u8 KML_DocumentOpen(s8 *name, KML_Document_t *doc)
{
 
u8 retvalue = 0;
if(doc == NULL) return(0);
 
KML_DocumentInit(doc); // intialize the document with resetvalues
doc->file = fopen_(name,'a'); // open a new file with the specified filename on the memorycard.
 
if(doc->file != NULL) // could the file be opened?
{
retvalue = 1; // the document could be created on the drive.
doc->state = DOC_OPENED; // change document state to opened. At next a placemark has to be opened.
fwrite_((void*)KML_DOCUMENT_HEADER, sizeof(KML_DOCUMENT_HEADER)-1,1,doc->file);// write the KML- footer to the document.
}
 
return(retvalue);
}
 
//________________________________________________________________________________________________________________________________________
// Function: DocumentClose(KML_Document_t *doc);
//
// Description: This function closes the document specified by doc.
//
//
// Returnvalue: none
//________________________________________________________________________________________________________________________________________
 
u8 KML_DocumentClose(KML_Document_t *doc)
{
 
u8 retvalue = 1;
 
if(doc == NULL) return(0);
while(doc->state != DOC_CLOSED) // close linestring, placemark and document before closing the file on the memorycard
{
switch(doc->state)
{
case DOC_LINESTRING_OPENED:
KML_LineStringEnd(doc); // write terminating tag to end linestring.
doc->state = DOC_PLACEMARK_OPENED;
break;
 
case DOC_PLACEMARK_OPENED: // write terminating tag to close placemark.
KML_PlaceMarkClose(doc);
doc->state = DOC_OPENED;
break;
case DOC_OPENED: // close the file on the memorycard
if(doc->file != NULL)
{
fwrite_((void*)KML_DOCUMENT_FOOTER, sizeof(KML_DOCUMENT_FOOTER)-1,1,doc->file); // write the KML- footer to the document.
fclose_(doc->file);
retvalue = 1;
}
doc->state = DOC_CLOSED;
break;
 
default:
doc->state = DOC_CLOSED;
break;
}
}
return(retvalue);
}
 
//________________________________________________________________________________________________________________________________________
// Function: u8 PlaceMarkOpen(s8 *name, File *file);
//
// Description: This function adds a placemark to the document.
//
//
// Returnvalue: none
//________________________________________________________________________________________________________________________________________
 
u8 KML_PlaceMarkOpen(s8 *name, KML_Document_t *doc)
{
 
u8 retvalue = 0;
 
if(doc->file != NULL)
{
doc->state = DOC_PLACEMARK_OPENED;
retvalue = 1;
fwrite_((void*)KML_PLACEMARK_HEADER, sizeof(KML_PLACEMARK_HEADER)-1,1,doc->file);
}
return(retvalue);
}
 
//________________________________________________________________________________________________________________________________________
// Function: u8 PlaceMarkClose(KML_PlaceMark_t *place, File *file);
//
// Description: This function ends the placemark opened before.
//
//
// Returnvalue: none
//________________________________________________________________________________________________________________________________________
 
u8 KML_PlaceMarkClose(KML_Document_t *doc)
{
 
u8 retvalue = 0; // close the Placemark-tag of the corosponding document.
 
if(doc->state == DOC_PLACEMARK_OPENED)
{
if(doc->file != NULL)
{
doc->state = DOC_OPENED;
fwrite_((void*)KML_PLACEMARK_FOOTER, sizeof(KML_PLACEMARK_FOOTER)-1,1,doc->file);
retvalue = 1;
}
}
return(retvalue);
}
 
//________________________________________________________________________________________________________________________________________
// Function: u8 LineStringBegin(KML_Document_t *doc);
//
// Description: This function ends the placemark opened before.
//
//
// Returnvalue: none
//________________________________________________________________________________________________________________________________________
 
u8 KML_LineStringBegin(KML_Document_t *doc)
{
 
u8 retvalue = 0;
if(doc->file != NULL)
{
doc->state = DOC_LINESTRING_OPENED;
fwrite_((void*)KML_LINESTRING_HEADER, sizeof(KML_LINESTRING_HEADER)-1,1,doc->file);
retvalue = 1;
}
 
return(retvalue);
}
 
//________________________________________________________________________________________________________________________________________
// Function: u8 LineStringEnd(KML_Document_t *doc)
//
// Description: This function ends the placemark opened before.
//
//
// Returnvalue: none
//________________________________________________________________________________________________________________________________________
 
u8 KML_LineStringEnd(KML_Document_t *doc)
{
 
u8 retvalue = 0;
if(doc->state == DOC_LINESTRING_OPENED);
if(doc->file != NULL)
{
doc->state = DOC_PLACEMARK_OPENED;
fwrite_((void*)KML_LINESTRING_FOOTER, sizeof(KML_LINESTRING_FOOTER)-1,1,doc->file);
retvalue = 1;
}
 
return(retvalue);
}
 
//________________________________________________________________________________________________________________________________________
// Function: u8 LineStringAddPoint(gps_data_t, KML_Document_t *doc)
//
// Description: This function adds a point to the specified document.
//
//
// Returnvalue: none
//________________________________________________________________________________________________________________________________________
 
u8 KML_LineStringAddPoint(gps_data_t * pgpsdata ,KML_Document_t *doc)
{
 
u8 retvalue = 0;
s8 string[50];
 
if(doc == NULL || pgpsdata == NULL) return(0);
 
if(pgpsdata->Status != INVALID)
{
if(doc->state == DOC_LINESTRING_OPENED)
{
if(doc->file != NULL)
{
s32 i1, i2;
i1 = GPSData.Longitude/10000000L;
i2 = abs(GPSData.Longitude%10000000L);
sprintf(string,"\r\n%+3ld.%07ld,",i1, i2);
fputs_(string, doc->file);
i1 = GPSData.Latitude/10000000L;
i2 = abs(GPSData.Latitude%10000000L);
sprintf(string," +%3ld.%07ld,",i1, i2);
fputs_(string, doc->file);
i1 = GPSData.Altitude/1000L;
i2 = abs(GPSData.Altitude%1000L);
sprintf(string," %+ld.%03ld",i1, i2);
fputs_(string, doc->file);
retvalue = 1;
}
}
}
 
return(retvalue);
}
 
//________________________________________________________________________________________________________________________________________
// Function: u8 KML_LoggGPSCoordinates(gps_data_t *, KML_Document_t *)
//
// Description: This function opens adds gpscoordinates to an KML-Document. The document will be opened, if not already done
//
//
// Returnvalue: none
//________________________________________________________________________________________________________________________________________
 
void KML_LoggGPSCoordinates(gps_data_t * pgpsdata, KML_Document_t *doc)
{
while(doc->state != DOC_LINESTRING_OPENED) // automatic create document with default filename on the card.
{
switch(doc->state)
{
case DOC_CLOSED: // document hasn't been opened yet therefore it will be initialized automatically
KML_DocumentInit(doc); // initialize the document to default values
if(KML_DocumentOpen("default.kml",doc)) // open the kml-document with a standardname.
{
doc->state = DOC_OPENED;
}
break;
 
case DOC_OPENED: // if a document has been opened before but no placemark exists:
if(KML_PlaceMarkOpen("MIKROKOPTER",doc))
{
doc->state = DOC_PLACEMARK_OPENED; // add a placemark to the document.
}
break;
 
case DOC_PLACEMARK_OPENED: // add linestring to the placemark
if(KML_LineStringBegin(doc))
{
doc->state = DOC_LINESTRING_OPENED;
}
break;
 
default:
break;
 
}
};
 
if(doc->state == DOC_LINESTRING_OPENED) // if the document was opened add coordinates to the document.
{
KML_LineStringAddPoint(pgpsdata , doc);
}
}
 
/branches/V0.1 killagreg/kml.h
0,0 → 1,50
#ifndef _KML_H
#define _KML_H
 
#include "fat16.h"
#include "ubx.h"
 
 
// possible state of an kml-document
typedef enum
{
DOC_CLOSED,
DOC_OPENED,
DOC_PLACEMARK_OPENED,
DOC_LINESTRING_OPENED,
DOC_END
}KML_DocState_t;
 
 
// structure of an kml-placemarkt
typedef struct kml_place
{
s8 name[10]; // the name of the placemark
s8 description[40]; // some text as a description to the placemark
} KML_PlaceMark_t;
 
 
 
// structure of an kml-document
typedef struct kml_doc
{
u8 name[40]; // name of the document
KML_DocState_t state; // state of the kml-document
File_t *file; // filepointer to the file where the data should be saved.
KML_PlaceMark_t place;
} KML_Document_t;
 
 
 
 
void KML_LoggGPSCoordinates(gps_data_t* pGPSData , KML_Document_t *); // intializes the kml-document with standard filename and adds points to the file
u8 KML_DocumentInit(KML_Document_t *); // Init the new kml-document
u8 KML_DocumentOpen(s8 *, KML_Document_t *); // opens a new kml-document. a new file is created on the sd-memorycard
u8 KML_DocumentClose(KML_Document_t *doc); // closes the specified document saving remaining data to the file.
u8 KML_PlaceMarkOpen(s8 *name, KML_Document_t *doc); // opens a new placemark within the open kml-document
u8 KML_PlaceMarkClose(KML_Document_t *doc); // closes the actual placemark
u8 KML_LineStringBegin(KML_Document_t *doc); // begins a new linestring within the actual placemark
u8 KML_LineStringEnd(KML_Document_t *doc); // close the actual linestring within the actual placemark
u8 KML_LineStringAddPoint(gps_data_t* pGPSData, KML_Document_t *); // adds a point from the gps (longitude, altitude, height) to the linestring
 
#endif //_KML_H
/branches/V0.1 killagreg/kml_header.h
0,0 → 1,91
//________________________________________________________________________________________________________________________________________
//
// Definition of KML header and footer elements for documents, placemarks and linestrings
//
//________________________________________________________________________________________________________________________________________
 
 
const s8 KML_DOCUMENT_HEADER[] =
{
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
"<kml xmlns=\"http://earth.google.com/kml/2.2\">\r\n"
"<Document>\r\n"
"<name>Mikrokopter GPS logging</name>\r\n"
"\r\n"
"<Style id=\"MK_gps-style\">\r\n"
"<LineStyle>\r\n"
"<color>ff0000ff</color>\r\n"
"<width>2</width>\r\n"
"</LineStyle>\r\n"
"</Style>\r\n"
};
 
 
 
 
//________________________________________________________________________________________________________________________________________
//
// footer of an KML- file.
//
//________________________________________________________________________________________________________________________________________
 
 
const s8 KML_DOCUMENT_FOOTER[] =
{
"</Document>\r\n"
"</kml>\r\n"
};
 
 
 
//________________________________________________________________________________________________________________________________________
//
// Header of an placemark
//
//________________________________________________________________________________________________________________________________________
 
const s8 KML_PLACEMARK_HEADER[] =
{
"<Placemark>\r\n"
"<name>flight</name>\r\n"
"<styleUrl>#MK_gps-style</styleUrl>\r\n"
};
 
//________________________________________________________________________________________________________________________________________
//
// Footer of an placemark
//
//________________________________________________________________________________________________________________________________________
 
const s8 KML_PLACEMARK_FOOTER[] =
{
"</Placemark>\r\n"
};
 
 
//________________________________________________________________________________________________________________________________________
//
// Footer of an placemark
//
//________________________________________________________________________________________________________________________________________
 
const s8 KML_LINESTRING_HEADER[] =
{
"<LineString>\r\n"
"<tessellate>1</tessellate>\r\n"
"<altitudeMode>absolute</altitudeMode>\r\n"
"<coordinates>\r\n"
};
 
//________________________________________________________________________________________________________________________________________
//
// Footer of an linestring
//
//________________________________________________________________________________________________________________________________________
 
const s8 KML_LINESTRING_FOOTER[] =
{
"\r\n</coordinates>"
"\r\n</LineString>\r\n"
};
 
/branches/V0.1 killagreg/led.c
1,6 → 1,6
#include "91x_lib.h"
#include "led.h"
 
 
void Led_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
8,18 → 8,12
SCU_APBPeriphClockConfig(__GPIO5, ENABLE); // Enable the GPIO5 Clock
/*Configure LED_GRN at pin GPIO5.6 and LED_ROT at pin GPIO5.7*/
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Direction = GPIO_PinOutput;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull ;
GPIO_InitStructure.GPIO_Alternate = GPIO_OutputAlt1 ;
GPIO_Init(GPIO5, &GPIO_InitStructure);
 
/* Configure SD_SWITCH at pin GPIO5.3*/
GPIO_InitStructure.GPIO_Direction = GPIO_PinInput;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull;
GPIO_InitStructure.GPIO_Alternate = GPIO_InputAlt1;
GPIO_Init(GPIO5, &GPIO_InitStructure);
LED_GRN_OFF;
LED_RED_OFF;
/branches/V0.1 killagreg/led.h
1,8 → 1,6
#ifndef _LED_H
#define _LED_H
 
#include "91x_lib.h"
 
#define LED_GRN_ON GPIO_WriteBit(GPIO5, GPIO_Pin_6, Bit_SET)
#define LED_GRN_OFF GPIO_WriteBit(GPIO5, GPIO_Pin_6, Bit_RESET)
#define LED_GRN_TOGGLE if (GPIO_ReadBit(GPIO5, GPIO_Pin_6)) LED_GRN_OFF; else LED_GRN_ON;
15,3 → 13,4
 
#endif //_LED_H
 
 
/branches/V0.1 killagreg/main.c
55,13 → 55,15
// + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// + POSSIBILITY OF SUCH DAMAGE.
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//#define MCLK96MHZ
const unsigned long _Main_Crystal = 25000;
#include <stdio.h>
#include "91x_lib.h"
#include "led.h"
#include "GPSUart.h"
#include "uart0.h"
#include "uart1.h"
//#include "uart2.h"
#include "GPS.h"
#include "uart.h"
#include "i2c.h"
#include "timer.h"
#include "spi_slave.h"
68,48 → 70,66
#include "fat16.h"
#include "usb.h"
#include "sdc.h"
#include "kml.h"
#include "main.h"
 
u32 TimerCompassUpdate;
u32 TimerI2CReadDelay;
u32 TimerDebugDataDelay;
u32 TimerKmlAddPointDelay;
 
u8 BeepTime;
void Init_Undef(void);
u16 BeepTime;
 
u8 ClearMKFlags = 0;
 
Param_t Parameter;
FC_t FC;
 
void SCU_Config(void)
{
/* configure PLL and set it as master clock source */
SCU_MCLKSourceConfig(SCU_MCLK_OSC); // set master clock source to external oscillator clock (25MHz) before diabling the PLL
SCU_PLLCmd(DISABLE); // now disable the PLL
#ifdef MCLK96MHZ
SCU_BRCLKDivisorConfig(SCU_BRCLK_Div2); // set BRCLK to MCLK/2 = 48MHz
SCU_PCLKDivisorConfig(SCU_PCLK_Div4); // set PCLK (APB bus clock) divisor to 4 (half Reference Clock)
SCU_RCLKDivisorConfig(SCU_RCLK_Div2); // set RCLK (Reference Clock) divisor to 1 (full PPL clock)
SCU_HCLKDivisorConfig(SCU_HCLK_Div2); // set HCLK (AHB bus clock) divisor to 1 (full Reference Clock)
SCU_PLLFactorsConfig(192,25,2); // PLL = 96 MHz, Feedback Divider N=192, Pre-Divider M=25, Post-Divider P=2
#else
SCU_BRCLKDivisorConfig(SCU_BRCLK_Div1); // set BRCLK to MCLK = 48MHz
SCU_PCLKDivisorConfig(SCU_PCLK_Div2); // set PCLK (APB bus clock) divisor to 2 (half Reference Clock)
SCU_RCLKDivisorConfig(SCU_RCLK_Div1); // set RCLK (Reference Clock) divisor to 1 (full PPL clock)
SCU_HCLKDivisorConfig(SCU_HCLK_Div1); // set HCLK (AHB bus clock) divisor to 1 (full Reference Clock)
SCU_PLLFactorsConfig(192,25,3); // PLL = 48 MHz, Feedback Divider N=192, Pre-Divider M=25, Post-Divider P=3
#endif
SCU_PLLCmd(ENABLE); // Enable PLL (is disabled by SCU_PLLFactorsConfig)
SCU_MCLKSourceConfig(SCU_MCLK_PLL); // set master clock source to PLL
}
 
 
//----------------------------------------------------------------------------------------------------
 
void OutputStartupData(void)
{
u8 text[20];
u8 msg[20];
SerialPutString("\n\r--------------\n\r");
sprintf(text,"NaviCtrl V%d.%d\n\r", VersionInfo.Major, VersionInfo.Minor);
SerialPutString(text);
sprintf(msg,"NaviCtrl V%d.%d\n\r", VersionInfo.Major, VersionInfo.Minor);
SerialPutString(msg);
}
 
//----------------------------------------------------------------------------------------------------
int main(void)
{
static u8 oldCompassCalState = 0;
u8 oldCompassCalState = 0;
u8 kml_state = 0;
u8 kml_count = 0;
KML_Document_t mydocument;
/* Configure the system clocks */
SCU_Config();
 
/* configure PLL and set it as master clock source */
SCU_MCLKSourceConfig(SCU_MCLK_OSC); // set master clock source to external oscillator clock (25MHz) before diabling the PLL
SCU_PLLCmd(DISABLE); // now disable the PLL
SCU_RCLKDivisorConfig(SCU_RCLK_Div1); // set RCLK (Reference Clock) divisor to 1 (full PPL clock)
SCU_HCLKDivisorConfig(SCU_HCLK_Div1); // set HCLK (AHB bus clock) divisor to 1 (full Reference Clock)
SCU_PCLKDivisorConfig(SCU_PCLK_Div2); // set PCLK (APB bus clock) divisor to 2 (half Reference Clock)
//SCU_BRCLKDivisorConfig(SCU_BRCLK_Div2); // set BRCLK to MCLK/2
SCU_PLLFactorsConfig(192,25,3); // PLL = 48 MHz, Feedback Divider N=192, Pre-Divider M=25, Post-Divider P=3
SCU_PLLCmd(ENABLE); // Enable PLL (is disabled by SCU_PLLFactorsConfig)
SCU_MCLKSourceConfig(SCU_MCLK_PLL); // set master clock source to PLL
KML_DocumentInit(&mydocument); // Initialize the new kml-document for further use.
 
 
/* Fill Version Info Structure */
VersionInfo.Major = VERSION_MAJOR;
VersionInfo.Minor = VERSION_MINOR;
123,113 → 143,135
Interrupt_Init();
// initialize timer 1
TIMER1_Init();
// initialize the LEDs
// initialize the LEDs (needs Timer 1)
Led_Init();
// initialize the debug UART1
UART1_Init();
OutputStartupData();
// initialize the uart to MKGPS module
GPS_UART0_Init();
// iniitalize the gps position controller
GPS_Init();
// initialize UART2 to FLIGHTCTRL
//UART2_Init();
// initialize UART0 (to MKGPS or MK3MAG)
UART0_Init();
// initialize usb
USB_ConfigInit();
// initialize SPI0 to FC
SPI0_Init();
// initialize i2c bus to MK3MAG
I2C1_Init();
// initialize fat16 partition on sd card
// initialize i2c bus to MK3MAG (needs Timer 1)
I2C1_Init();
// initialize the gps position controller (needs Timer 1)
GPS_Init();
// initialize fat16 partition on sd card (needs Timer 1)
Fat16_Init();
 
// get version from MK3MAG
I2C_Version.Major = 0xFF;
SendI2C_Command(I2C_CMD_VERSION);
I2C_Version.Minor = 0xFF;
I2C_Version.Patch = 0xFF;
I2C1_SendCommand(I2C_CMD_VERSION);
 
TimerCompassUpdate = SetDelay(50);
while (!CheckDelay(TimerCompassUpdate));
TimerCompassUpdate = SetDelay(5);
TimerI2CReadDelay = SetDelay(5);
TimerKmlAddPointDelay = SetDelay(250);
 
 
SerialPutString("\r\n---------------------------------------------");
/*
ReadSetting(1);
*/
SerialPutString("Init done\n\r.");
SerialPutString("--------------\n\n\r");
*/
SerialPutString("\r\n---------------------------------------------\r\n\r\n");
for (;;)
{
if(rxd_buffer_locked)
if(rxd_buffer_locked) // new incomming command
{
UART1_ProcessRxData();
UART1_TransmitTxData();
UART1_ProcessRxData(); // process command
UART1_TransmitTxData(); // send answer
}
UpdateSPI_Buffer();
SPI_CheckSlaveSelect();
UART1_Transmit(); // empty txd buffer
// ----------- I2C Timing -------------------------
if (CheckDelay(TimerCompassUpdate))
{
if(oldCompassCalState != CompassCalState)
{
oldCompassCalState = CompassCalState;
TimerCompassUpdate = SetDelay(25);
SendI2C_Command(I2C_CMD_WRITE_CAL);
}
else
{
LED_GRN_TOGGLE;
TimerCompassUpdate = SetDelay(25);
SendI2C_Command(I2C_CMD_READ_HEADING);
}
// ------------------------- I2C Timing --------------------------------
if (CheckDelay(TimerCompassUpdate))
{
// check for hanging I2C bus
if(CheckDelay(I2C1_Timeout))
{ // reset I2C
I2C1_Deinit();
I2C1_Init();
}
else
{
if(oldCompassCalState != CompassCalState)
{
oldCompassCalState = CompassCalState;
TimerCompassUpdate = SetDelay(25); // every 25 ms
I2C1_SendCommand(I2C_CMD_WRITE_CAL);
}
else
{
TimerCompassUpdate = SetDelay(25); // every 25 ms
I2C1_SendCommand(I2C_CMD_READ_HEADING);
}
}
}
}
if (CheckDelay(TimerI2CReadDelay))
{
I2C1_ReadAnswer();
TimerI2CReadDelay = SetDelay(1000);
}
// ---------------- Debug Timing ----------------------------------
if (CheckDelay(TimerDebugDataDelay))
{
UART1_TransmitTxData();
TimerDebugDataDelay = SetDelay(500);
}
// ---------------- KML Timing ------------------------------------
if(CheckDelay(TimerKmlAddPointDelay))
{
TimerKmlAddPointDelay = SetDelay(500);
switch(kml_state)
{
case 0:
if((GPSData.Status != INVALID) && (GPSData.Flags & FLAG_GPSFIXOK) && (GPSData.SatFix == SATFIX_3D))
{
if(KML_DocumentOpen("Flight01.kml",&mydocument)) // create a new kml-document on the memorycard.
{
SerialPutString("\r\nopening kml-file\r\nadding data");
kml_state = 1; // goto next step
}
else
{
SerialPutString("\r\nError opening kml-file");
// try to reinitialize the FAT16
if(0 != Fat16_Init()) TimerKmlAddPointDelay = SetDelay(5000); // try again in 5 sec
}
}
break; // document.state will be changed to DOC_OPENED automatic.
case 1: // linestring opened, so datapoint (gps_coordinates) can be added to the document.
if(kml_count++ < 20) // add 10 datapoints to the document.
{
KML_LoggGPSCoordinates(&GPSData, &mydocument);
}
else // after the datapoints have been written to the document close the document.
{
KML_DocumentClose(&mydocument);
SerialPutString("\r\nfile closed");
kml_state = 2;
}
break;
 
if (CheckDelay(TimerI2CReadDelay))
{
if (I2C_ReadRequest)
{
I2C_ReadRequest= 0;
I2C_Direction = I2C_MODE_RECEIVER;
I2C_GenerateStart(I2C1, ENABLE);
default:
break; // all data has been written to card. open new document to add new data.
}
}
TimerI2CReadDelay = SetDelay(1000);
}
 
if (CheckDelay(TimerDebugDataDelay))
{
Request_GPS_Position = 1;
UART1_TransmitTxData();
TimerDebugDataDelay = SetDelay(500);
}
// ----------------------------------------------------
}
}
}
 
 
//________________________________________________________________________________________________________________________________________
// Funtion: EXTIT1_IRQHandler(void);
//
// Description: This function handles the external interrupts from port 5.3 (SD_SWITCH)
//
//
// Returnvalue: none
//________________________________________________________________________________________________________________________________________
void EXTIT1_IRQHandler(void)
{
VIC_ITCmd(EXTIT1_ITLine, DISABLE);
if(WIU_GetITStatus(WIU_Line11) != RESET)
{
BeepTime = 100;
Fat16_Init(); // initialize sd-card file system.
 
WIU_ClearFlag(WIU_Line1);
WIU_ClearITPendingBit(WIU_Line11);
}
VIC_ITCmd(EXTIT1_ITLine, ENABLE);
}
 
/branches/V0.1 killagreg/main.h
1,7 → 1,6
#ifndef _MAIN_H
#define _MAIN_H
 
#include "91x_lib.h"
 
#define VERSION_MAJOR 0
#define VERSION_MINOR 1
9,19 → 8,31
 
extern u32 TimerCompassUpdate;
extern u32 TimerI2CReadDelay;
extern u8 BeepTime;
extern u16 BeepTime;
extern u8 ClearMKFlags;
void Interrupt_Init(void);
 
typedef struct
{
u8 User1;
u8 User2;
u8 User3;
u8 User4;
u8 User5;
u8 User6;
u8 User7;
u8 User8;
u8 ActiveSetting;
u8 User1;
u8 User2;
u8 User3;
u8 User4;
u8 User5;
u8 User6;
u8 User7;
u8 User8;
u8 NaviGpsModeControl;
u8 NaviGpsGain;
u8 NaviGpsP;
u8 NaviGpsI;
u8 NaviGpsD;
u8 NaviGpsACC;
u8 NaviGpsMinSat;
u8 NaviStickThreshold;
u8 NaviRadiusAlert;
u8 LowVoltageWarning;
} __attribute__((packed)) Param_t;
 
typedef struct
35,7 → 46,17
u8 Poti3;
u8 Poti4;
u8 RC_Quality;
u8 MotorsOn;
u8 UBat;
// MK_Flags
#define MKFLAG_MOTOR_RUN 0x01
#define MKFLAG_FLY 0x02
#define MKFLAG_CALIBRATE 0x04
#define MKFLAG_START 0x08
#define MKFLAG_EMERGENCY_LANDING 0x10
#define MKFLAG_RESERVE1 0x20
#define MKFLAG_RESERVE2 0x40
#define MKFLAG_RESERVE3 0x80
u8 MKFlags;
} __attribute__((packed)) FC_t;
 
 
/branches/V0.1 killagreg/menu.c
58,7 → 58,9
#include "91x_lib.h"
#include "printf_P.h"
#include "main.h"
#include "GPSUart.h"
#include "ubx.h"
#include "GPS.h"
#include "timer.h"
#include "i2c.h"
#include "spi_slave.h"
#include "menu.h"
91,9 → 93,9
// Display with 20 characters in 4 lines
void LCD_PrintMenu(void)
{
static u8 MaxMenuItem = 9;
static u8 MaxMenuItem = 12;
static u8 MenuItem=0;
s16 i1,i2,i3;
s32 i1,i2;
// if KEY1 is activated goto previous menu item
if(RemoteButtons & KEY1)
{
132,10 → 134,10
case 1:
if (GPSData.Status == INVALID)
{
LCD_printfxy(0,0,"No GPS data! ");
LCD_printfxy(0,1," ");
LCD_printfxy(0,2," ");
LCD_printfxy(0,3," ");
LCD_printfxy(0,0,"No GPS data");
LCD_printfxy(0,1,"Lon: ");
LCD_printfxy(0,2,"Lat: ");
LCD_printfxy(0,3,"Alt: ");
}
else // newdata or processed
{
154,26 → 156,24
LCD_printfxy(0,0,"Sats:%02d Fix:?? ", GPSData.NumOfSats);
break;
}
i1 = (s16)(GPSData.Longitude/10000000L);
i2 = abs((s16)((GPSData.Longitude%10000000L)/10000L));
i3 = abs((s16)(((GPSData.Longitude%10000000L)%10000L)/10L));
LCD_printfxy(0,1,"Lon: %3d.%.3d%.3d deg",i1, i2, i3);
i1 = (s16)(GPSData.Latitude/10000000L);
i2 = abs((s16)((GPSData.Latitude%10000000L)/10000L));
i3 = abs((s16)(((GPSData.Latitude%10000000L)%10000L)/10L));
LCD_printfxy(0,2,"Lat: %3d.%.3d%.3d deg",i1, i2, i3);
i1 = (s16)(GPSData.Altitude/1000L);
i2 = abs((s16)(GPSData.Altitude%1000L));
LCD_printfxy(0,3,"Alt: %3d.%.3d m",i1, i2);
i1 = GPSData.Longitude/10000000L;
i2 = abs(GPSData.Longitude%10000000L);
LCD_printfxy(0,1,"Lon:%+3ld.%07ld deg",i1, i2);
i1 = GPSData.Latitude/10000000L;
i2 = abs(GPSData.Latitude%10000000L);
LCD_printfxy(0,2,"Lat:%+3ld.%07ld deg",i1, i2);
i1 = GPSData.Altitude/1000L;
i2 = abs(GPSData.Altitude%1000L);
LCD_printfxy(0,3,"Alt:%4ld.%03ld m",i1, i2);
}
break;
case 2:
if (GPSData.Status == INVALID)
{
LCD_printfxy(0,0,"No GPS data! ");
LCD_printfxy(0,1," ");
LCD_printfxy(0,2," ");
LCD_printfxy(0,3," ");
LCD_printfxy(0,0,"No GPS data");
LCD_printfxy(0,1,"Speed N: ");
LCD_printfxy(0,2,"Speed E: ");
LCD_printfxy(0,3,"Speed T: ");
}
else // newdata or processed
{
192,64 → 192,91
LCD_printfxy(0,0,"Sats:%02d Fix:?? ", GPSData.NumOfSats);
break;
}
i1 = (s16)(GPSData.Speed_North);
i2 = (s16)(GPSData.Speed_East);
i3 = (s16)(GPSData.Speed_Top);
LCD_printfxy(0,1,"Speed N: %4i cm/s",i1);
LCD_printfxy(0,2,"Speed E: %4i cm/s",i2);
LCD_printfxy(0,3,"Speed T: %4i cm/s",i3);
LCD_printfxy(0,1,"Speed N: %+4ld cm/s",GPSData.Speed_North);
LCD_printfxy(0,2,"Speed E: %+4ld cm/s",GPSData.Speed_East);
LCD_printfxy(0,3,"Speed T: %+4ld cm/s",GPSData.Speed_Top);
}
break;
case 3:
LCD_printfxy(0,0,"GPS UTC Time");
if (!SystemTime.Valid)
{
LCD_printfxy(0,0,"No GPS time data!");
LCD_printfxy(0,0,"GPS UTC Time");
LCD_printfxy(0,1," ");
LCD_printfxy(0,2," ");
LCD_printfxy(0,2," No time data! ");
LCD_printfxy(0,3," ");
}
else // newdata or processed
{
LCD_printfxy(0,0,"GPS UTC Time: ");
LCD_printfxy(0,1,"");
LCD_printfxy(0,2,"Date: %02i/%02i/%04i ",SystemTime.Month, SystemTime.Day, SystemTime.Year);
LCD_printfxy(0,1," ");
LCD_printfxy(0,2,"Date: %02i/%02i/%04i",SystemTime.Month, SystemTime.Day, SystemTime.Year);
LCD_printfxy(0,3,"Time: %02i:%02i:%02i.%03i", SystemTime.Hour, SystemTime.Min, SystemTime.Sec, SystemTime.mSec);
}
break;
case 4: // RC stick controls from FC
case 4: // Navi Params from FC
LCD_printfxy(0,0,"NaviMode: %3i" , Parameter.NaviGpsModeControl);
LCD_printfxy(0,1,"G :%3i P :%3i ",Parameter.NaviGpsGain, Parameter.NaviGpsP);
LCD_printfxy(0,2,"I :%3i D :%3i ",Parameter.NaviGpsI, Parameter.NaviGpsD);
LCD_printfxy(0,3,"ACC:%3i SAT:%3i ",Parameter.NaviGpsACC, Parameter.NaviGpsMinSat);
break;
case 5:
LCD_printfxy(0,0,"Home Position");
if(GPSHomePosition.Status == INVALID)
{
LCD_printfxy(0,1," ");
LCD_printfxy(0,2," Is not set. ");
LCD_printfxy(0,3," ");
}
else
{
i1 = GPSHomePosition.Longitude/10000000L;
i2 = abs(GPSHomePosition.Longitude%10000000L);
LCD_printfxy(0,1,"Lon: %3ld.%07ld deg",i1, i2);
i1 = GPSHomePosition.Latitude/10000000L;
i2 = abs(GPSHomePosition.Latitude%10000000L);
LCD_printfxy(0,2,"Lat: %3ld.%07ld deg",i1, i2);
i1 = GPSHomePosition.Altitude/1000L;
i2 = abs(GPSHomePosition.Altitude%1000L);
LCD_printfxy(0,3,"Alt:%4ld.%03ld m",i1, i2);
}
break;
case 6: // RC stick controls from FC
LCD_printfxy(0,0,"RC-Sticks" );
LCD_printfxy(0,1,"Ni:%4i Ro:%4i ",FC.StickNick, FC.StickRoll);
LCD_printfxy(0,2,"Gs:%4i Ya:%4i ",FC.StickGas, FC.StickYaw);
break;
case 5: // RC poti controls from FC
case 7: // RC poti controls from FC
LCD_printfxy(0,0,"RC-Potis" );
LCD_printfxy(0,1,"Po1:%3i Po2:%3i ",FC.Poti1, FC.Poti2);
LCD_printfxy(0,2,"Po3:%3i Po4:%3i ",FC.Poti3, FC.Poti4);
break;
case 6: // attitude from FC
case 8: // attitude from FC
LCD_printfxy(0,0,"IntNick: %5i", FromFlightCtrl.IntegralNick);
LCD_printfxy(0,1,"IntRoll: %5i", FromFlightCtrl.IntegralRoll);
LCD_printfxy(0,2,"AccNick: %5i", FromFlightCtrl.AccNick);
LCD_printfxy(0,3,"AccRoll: %5i", FromFlightCtrl.AccRoll);
break;
case 7: // gyros from FC
case 9: // gyros from FC
LCD_printfxy(0,0,"GyroNick: %4i", FromFlightCtrl.GyroNick);
LCD_printfxy(0,1,"GyroRoll: %4i", FromFlightCtrl.GyroRoll);
LCD_printfxy(0,2,"GyroYaw: %4i", FromFlightCtrl.GyroYaw);
break;
case 8: // Remote Control Level from FC
case 10: // Remote Control Level from FC
LCD_printfxy(0,0,"RC-Level: %3i", FC.RC_Quality);
LCD_printfxy(0,1,"Motors On: %1i", FC.MotorsOn);
LCD_printfxy(0,1,"Ubat: %3i", FC.UBat);
LCD_printfxy(0,2,"CompHeading: %3i", I2C_Heading.Heading);
LCD_printfxy(0,3,"GyroHeading: %3i", FromFlightCtrl.GyroHeading);
break;
case 9: // User Parameter
case 11: // User Parameter
LCD_printfxy(0,0,"UP1:%3i UP2:%3i ",Parameter.User1,Parameter.User2);
LCD_printfxy(0,1,"UP3:%3i UP4:%3i ",Parameter.User3,Parameter.User4);
LCD_printfxy(0,2,"UP5:%3i UP6:%3i ",Parameter.User5,Parameter.User6);
LCD_printfxy(0,3,"UP7:%3i UP8:%3i ",Parameter.User7,Parameter.User8);
break;
case 12: // MK3MAG
LCD_printfxy(0,0,"MK3MAG V%i.%i.%i",I2C_Version.Major,I2C_Version.Minor, I2C_Version.Patch);
break;
default:
MaxMenuItem = MenuItem - 1;
MenuItem = 0;
/branches/V0.1 killagreg/menu.h
1,7 → 1,6
#ifndef _MENU_H
#define _MENU_H
 
#include "91x_lib.h"
 
#define DISPLAYBUFFSIZE 80
 
/branches/V0.1 killagreg/printf_P.c
88,7 → 88,7
#else
#include <varargs.h>
#endif
 
#include "91x_lib.h"
#include "menu.h"
 
 
/branches/V0.1 killagreg/sdc.c
57,10 → 57,10
#include <stdio.h>
#include <string.h>
#include "91x_lib.h"
#include "uart.h"
#include "timer.h"
#include "uart1.h"
#include "sdc.h"
#include "ssc.h"
#include "timer.h"
#include "main.h"
#include "crc16.h"
 
68,7 → 68,7
// Module name: sdc.c
// Compiler used: avr-gcc 3.4.5
// Last Modifikation: 08.06.2008
// Version: 1.06
// Version: 1.07
// Authors: Stephan Busker, Gregor Stobrawa
// Description: Source files for connecting to an sd-card using the SSC
//
181,8 → 181,26
return(crc);
}
 
u8 SDC_WaitForBusy(u32 timeout)
{
u8 rsp = 0;
u32 timestamp = 0;
 
SSC_ClearRxFifo();
SSC_Enable(); // enable chipselect.
timestamp = SetDelay(timeout);
do
{
rsp = SSC_GetChar();
if(CheckDelay(timestamp)) break;
}while(rsp != 0xFF); // wait while card is busy (data out low)
return(rsp);
}
 
 
 
//________________________________________________________________________________________________________________________________________
// Function: SDC_SendCMD(u8 CmdNo, u32 arg);
// Function: SDC_SendCMDR1(u8 CmdNo, u32 arg);
//
// Description: This function send a command frame to the SD-Card in spi-mode.
//
189,27 → 207,17
//
// Returnvalue: The function returns the first response byte like for R1 commands
//________________________________________________________________________________________________________________________________________
u8 SDC_SendCMD(u8 CmdNo, u32 arg)
u8 SDC_SendCMDR1(u8 CmdNo, u32 arg)
{
u8 r1;
u32 Timeout = 0;
u16 timeout = 0;
u16 a;
u8 cmd[6];
 
SSC_ClearRxFifo(); // clear the rx fifo
SSC_Enable(); // enable chipselect.
// wait if card is busy
Timeout = SetDelay(1000);
do
{
r1 = SSC_GetChar();
if (CheckDelay(Timeout))
{
return(r1);
}
}while(r1 != 0xFF);
 
 
SDC_WaitForBusy(500); // wait 500ms until card is busy
SSC_ClearRxFifo(); // clear the rx fifo
SSC_GetChar(); // dummy to sync
 
cmd[0] = 0x40|CmdNo; // set command index
223,11 → 231,11
SSC_PutChar(cmd[a]);
}
SSC_ClearRxFifo(); // clear the rx fifo to discard the bytes received during the transmission of the 6 command bytes
Timeout = SetDelay(50);
 
do
{
r1 = SSC_GetChar(); // get byte from sd-card
if (CheckDelay(Timeout)) break;
if (timeout++ >500) break;
}while(r1 == 0xFF); // wait for the response byte from sd-card.
return(r1);
}
235,7 → 243,7
 
//________________________________________________________________________________________________________________________________________
// Function: SDC_SendACMDR1(u8 CmdNo, u32 arg);
//
//
// Description: This function send a application command frame to the SD-Card in spi-mode.
//
//
243,10 → 251,10
//________________________________________________________________________________________________________________________________________
u8 SDC_SendACMDR1(u8 CmdNo, u32 arg)
{
u8 r1;
r1 = SDC_SendCMD(CMD_APP_CMD, 0UL);
u8 r1 = 0xFF;
r1 = SDC_SendCMDR1(CMD_APP_CMD, 0UL);
if(r1 & R1_BAD_RESPONSE) return(r1);
r1 = SDC_SendCMD(CmdNo, arg);
r1 = SDC_SendCMDR1(CmdNo, arg);
return(r1);
}
 
263,12 → 271,11
SD_Result_t SDC_GetData(u8 CmdNo, u32 addr, u8 *Buffer, u32 len)
{
u8 rsp;
u32 Timeout;
u16 a, Crc16;
u16 a, crc16;
SD_Result_t result = SD_ERROR_UNKNOWN;
 
// send the command
rsp = SDC_SendCMD(CmdNo, addr);
rsp = SDC_SendCMDR1(CmdNo, addr);
if (rsp != R1_NO_ERR)
{
result = SD_ERROR_BAD_RESPONSE;
275,7 → 282,6
goto end;
}
SSC_ClearRxFifo();
Timeout = SetDelay(200);
do
{
rsp = SSC_GetChar();
284,11 → 290,6
result = SD_ERROR_READ_DATA;
goto end;
}
if (CheckDelay(Timeout))
{
result = SD_ERROR_TIMEOUT;
goto end;
}
}while(rsp != DATA_START_TOKEN);
// data start token received
for (a = 0; a < len; a++) // read the block from the SSC
296,10 → 297,10
Buffer[a] = SSC_GetChar();
}
// Read two bytes CRC16-Data checksum
Crc16 = SSC_GetChar(); // highbyte fisrt
Crc16 = (Crc16<<8)|SSC_GetChar(); // lowbyte last
if(Crc16 != CRC16(Buffer, len)) result = SD_ERROR_CRC_DATA;
else result = SD_SUCCESS;
crc16 = SSC_GetChar(); // highbyte fisrt
crc16 = (crc16<<8)|SSC_GetChar(); // lowbyte last
/* if(crc16 != CRC16(Buffer, len)) result = SD_ERROR_CRC_DATA;
else */result = SD_SUCCESS;
end:
if(result != SD_SUCCESS)
391,16 → 392,18
 
SD_Result_t SDC_Init(void)
{
u32 Timeout = 0;
u32 timeout = 0;
u8 text[50];
u8 rsp[6]; // SD-SPI response buffer
SD_Result_t result = SD_ERROR_UNKNOWN;
SerialPutString("SDC init...");
if(SD_SWITCH) // init only if the SD-Switch is indicating a card in the slot
{
SerialPutString("\r\n SSC init...");
SSC_Init();
SerialPutString("ok");
 
SerialPutString("\r\n SDC init...");
SDCardInfo.Valid = 0;
/* The host shall supply power to the card so that the voltage is reached to Vdd_min within 250ms and
start to supply at least 74 SD clocks to the SD card with keeping cmd line to high. In case of SPI
408,37 → 411,36
SSC_Disable(); // set SD_CS high
SSC_ClearRxFifo(); // clear the rx fifo
for (Timeout = 0; Timeout < 15; Timeout++) // 15*8 = 120 cycles
for (timeout = 0; timeout < 15; timeout++) // 15*8 = 120 cycles
{
SSC_PutChar(0xFF);
}
// switch to idle state
Timeout = SetDelay(200);
while(SDC_SendCMD(CMD_GO_IDLE_STATE, 0UL) != R1_IDLE_STATE)
while(SDC_SendCMDR1(CMD_GO_IDLE_STATE, 0UL) != R1_IDLE_STATE)
{
if (CheckDelay(Timeout))
if (timeout++ > 20)
{
SerialPutString("reset timeout.\r\n");
SerialPutString("reset timeout");
result = SD_ERROR_RESET;
goto end;
}
}
// enable crc feature
if(SDC_SendCMD(CMD_CRC_ON_OFF, 1UL) != R1_IDLE_STATE)
/* if(SDC_SendCMDR1(CMD_CRC_ON_OFF, 1UL) != R1_IDLE_STATE)
{
sprintf(text,"Bad cmd59 R1=%02X.\r\n", rsp[0]);
sprintf(text,"Bad cmd59 R1=%02X.", rsp[0]);
SerialPutString(text);
result = SD_ERROR_BAD_RESPONSE;
goto end;
}
}*/
// check for card hw version
// 2.7-3.6V Range = 0x01, check pattern 0xAA
rsp[0] = SDC_SendCMD(CMD_SEND_IF_COND, 0x000001AA);
rsp[0] = SDC_SendCMDR1(CMD_SEND_IF_COND, 0x000001AA);
// answer to cmd58 is an R7 response (R1+ 4Byte IFCond)
if(rsp[0] & R1_BAD_RESPONSE)
{
sprintf(text,"Bad cmd8 R1=%02X.\r\n", rsp[0]);
sprintf(text,"Bad cmd8 R1=%02X.", rsp[0]);
SerialPutString(text);
result = SD_ERROR_BAD_RESPONSE;
goto end;
453,9 → 455,9
// Ver2.00 or later SD Memory Card
// reading the remaining bytes of the R7 response
SDCardInfo.Version = VER_20;
for(Timeout = 1; Timeout < 5; Timeout++)
for(timeout = 1; timeout < 5; timeout++)
{
rsp[Timeout] = SSC_GetChar();
rsp[timeout] = SSC_GetChar();
}
//check pattern
if(rsp[4]!= 0xAA)
473,11 → 475,11
}
}
rsp[0] = SDC_SendCMD(CMD_READ_OCR, 0UL);
rsp[0] = SDC_SendCMDR1(CMD_READ_OCR, 0UL);
// answer to cmd58 is an R3 response (R1 + 4Byte OCR)
if(rsp[0] & R1_BAD_RESPONSE)
{
sprintf(text,"Bad cmd58 R1 %02x.\r\n", rsp[0]);
sprintf(text,"Bad cmd58 R1 %02x.", rsp[0]);
SerialPutString(text);
result = SD_ERROR_BAD_RESPONSE;
goto end;
484,39 → 486,39
}
if(rsp[0] & R1_ILLEGAL_CMD)
{
SerialPutString("Not an SD-CARD.\r\n");
SerialPutString("Not an SD-CARD.");
result = SD_ERROR_NO_SDCARD;
goto end;
}
// read 4 bytes of OCR register
for(Timeout = 1; Timeout < 5; Timeout++)
for(timeout = 1; timeout < 5; timeout++)
{
rsp[Timeout] = SSC_GetChar();
rsp[timeout] = SSC_GetChar();
}
// NavicCtrl uses 3.3 V, therefore check for bit 20 & 21
if((rsp[2] & 0x30) != 0x30)
{
// supply voltage is not supported by sd-card
SerialPutString("Card is incompatible to 3.3V.\r\n");
SerialPutString("Card is incompatible to 3.3V.");
result = SD_ERROR_BAD_VOLTAGE_RANGE;
goto end;
}
// Initialize the sd-card sending continously ACMD_SEND_OP_COND (only supported by SD cards)
Timeout = SetDelay(1000);
timeout = SetDelay(2000); // set timeout to 2000 ms (large cards tend to longer)
do
{
rsp[0] = SDC_SendACMDR1(ACMD_SEND_OP_COND, 0UL);
if(rsp[0] & R1_BAD_RESPONSE)
{
sprintf(text,"Bad Acmd41 R1=%02X.\r\n", rsp[0]);
sprintf(text,"Bad Acmd41 R1=%02X.", rsp[0]);
SerialPutString(text);
result = SD_ERROR_BAD_RESPONSE;
goto end;
}
if(CheckDelay(Timeout))
if(CheckDelay(timeout))
{
SerialPutString("Init timeout.\r\n");
SerialPutString("Init timeout.");
result = SD_ERROR_INITIALIZE;
goto end;
}
524,19 → 526,21
if(rsp[0] != R1_NO_ERR)
{
SerialPutString("Init error.\r\n");
SerialPutString("Init error.");
result = SD_ERROR_INITIALIZE;
goto end;
}
/* set block size to 512 bytes */
if(SDC_SendCMD(CMD_SET_BLOCKLEN, 512UL) != R1_NO_ERR)
if(SDC_SendCMDR1(CMD_SET_BLOCKLEN, 512UL) != R1_NO_ERR)
{
SerialPutString("Error setting block length to 512.\r\n");
SerialPutString("Error setting block length to 512.");
result = SD_ERROR_SET_BLOCKLEN;
goto end;
}
//SSC_Disable(); // set SD_CS high
// here is the right place to inrease the SPI boud rate to maximum
//SSC_Enable(); // set SD_CS high
 
// read CID register
result = SDC_GetCID((u8 *)&SDCardInfo.CID);
550,7 → 554,7
result = SDC_GetCSD((u8 *)&SDCardInfo.CSD);
if(result != SD_SUCCESS)
{
SerialPutString("Error reading CSD.\r\n");
SerialPutString("Error reading CSD.");
goto end;
}
604,19 → 608,22
switch(SDCardInfo.Version)
{
case VER_1X:
SerialPutString("SD-CARD V1.x\r\n");
SerialPutString(" SD-CARD V1.x");
break;
case VER_20:
SerialPutString("SD-CARD V2.0 or later\r\n");
SerialPutString(" SD-CARD V2.0 or later");
default:
break;
}
u16 mb_size = (u16)(SDCardInfo.Capacity/(1024L*1024L));
sprintf(text, "Capacity = %i MB\r\n", mb_size);
sprintf(text, "\r\n Capacity = %i MB", mb_size);
SerialPutString(text);
SDC_PrintCID((u8 *)&SDCardInfo.CID);
SDCardInfo.Valid = 1;
// jump point for error condition before
end:
SSC_Disable();
}
else
{
623,10 → 630,8
SSC_Deinit();
SDCardInfo.Valid = 0;
result = SD_ERROR_NOCARD;
SerialPutString("No Card in Slot.\r\n");
SerialPutString("No Card in Slot.");
}
// jump point for error condition before
end:
return(result);
}
 
642,7 → 647,7
 
SD_Result_t SDC_Deinit(void)
{
SerialPutString("SDC deinit...");
SerialPutString("\r\n SDC deinit...");
SSC_Deinit();
 
SDCardInfo.Valid = 0;
649,7 → 654,7
SDCardInfo.Capacity = 0;
SDCardInfo.Version = VER_UNKNOWN;
 
SerialPutString("ok\r\n");
SerialPutString("ok");
return(SD_SUCCESS);
}
 
666,12 → 671,12
SD_Result_t SDC_PutSector(u32 addr, const u8 *Buffer)
{
u8 rsp;
u16 a, Crc16;
u32 Timeout = 0;
u16 a, crc16;
u16 timeout = 0;
SD_Result_t result = SD_ERROR_UNKNOWN;
 
addr = addr << 9; // convert sectoradress to byteadress
rsp = SDC_SendCMD(CMD_WRITE_SINGLE_BLOCK, addr);
rsp = SDC_SendCMDR1(CMD_WRITE_SINGLE_BLOCK, addr);
if (rsp != R1_NO_ERR)
{
result = SD_ERROR_BAD_RESPONSE;
678,11 → 683,11
goto end;
}
SSC_ClearRxFifo();
for (a=0;a<100;a++) // at least one byte
for (a=0;a<20;a++) // at least one byte
{
SSC_GetChar();
}
Crc16 = CRC16(Buffer, 512); // calc checksum for data block
crc16 = CRC16(Buffer, 512); // calc checksum for data block
SSC_PutChar(DATA_START_TOKEN); // send data start of header to the SSC
for (a=0;a<512;a++) // transmit one sector (normaly 512bytes) of data to the sdcard.
690,14 → 695,13
SSC_PutChar(Buffer[a]);
}
// write two bytes of crc16 to the sdcard
SSC_PutChar((u8)(Crc16>>8)); // write high byte first
SSC_PutChar((u8)(0x00FF&Crc16)); // lowbyte last
SSC_PutChar((u8)(crc16>>8)); // write high byte first
SSC_PutChar((u8)(0x00FF&crc16)); // lowbyte last
SSC_ClearRxFifo();
Timeout = SetDelay(500);
do // wait for data response token
{
rsp = SSC_GetChar();
if(CheckDelay(Timeout))
if(timeout++ > 500)
{
result = SD_ERROR_TIMEOUT;
goto end;
723,19 → 727,16
break;
 
}
// wait until the sdcard is busy.
Timeout = SetDelay(1000);
do
// wait 2 seconds until the sdcard is busy.
rsp = SDC_WaitForBusy(2000);
if(rsp != 0xFF)
{
rsp = SSC_GetChar();
if (CheckDelay(Timeout))
{
result = SD_ERROR_TIMEOUT;
goto end;
}
}while(rsp != 0xFF);
result = SD_ERROR_TIMEOUT;
goto end;
}
 
// check card status
rsp = SDC_SendCMD(CMD_SEND_STATUS, 0);
rsp = SDC_SendCMDR1(CMD_SEND_STATUS, 0);
// first byte of R2 response is like R1 response
if(rsp != R1_NO_ERR)
{
/branches/V0.1 killagreg/sdc.h
1,7 → 1,6
#ifndef _SDC_H
#define _SDC_H
 
#include "91x_lib.h"
 
//________________________________________________________________________________________________________________________________________
//
/branches/V0.1 killagreg/settings.c
60,7 → 60,7
#include "91x_lib.h"
#include "fat16.h"
#include "settings.h"
#include "uart.h"
#include "uart1.h"
 
struct str_setting_parameter CFG_Parameter[] =
{
/branches/V0.1 killagreg/spi_slave.c
58,9 → 58,9
#include <string.h>
#include "91x_lib.h"
#include "led.h"
#include "GPSUart.h"
//#include "GPSUart.h"
#include "GPS.h"
#include "uart.h"
#include "uart1.h"
#include "spi_slave.h"
#include "i2c.h"
#include "timer.h"
79,8 → 79,8
} SPI_State_t;
 
//communication packets
FromFlightCtrl_t FromFlightCtrl;
ToFlightCtrl_t ToFlightCtrl;
volatile FromFlightCtrl_t FromFlightCtrl;
volatile ToFlightCtrl_t ToFlightCtrl;
 
// tx packet buffer
#define SPI_TXBUFFER_LEN (2 + sizeof(ToFlightCtrl)) // 2 bytes at start are for synchronization
210,7 → 210,7
GPIO_InitTypeDef GPIO_InitStructure;
SSP_InitTypeDef SSP_InitStructure;
 
SerialPutString("SPI init...");
SerialPutString("\r\n SPI init...");
 
SCU_APBPeriphClockConfig(__GPIO2 ,ENABLE);
SCU_APBPeriphClockConfig(__SSP0 ,ENABLE);
217,6 → 217,7
 
GPIO_DeInit(GPIO2);
//SSP0_CLK, SSP0_MOSI, SSP0_NSS pins
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Direction = GPIO_PinInput;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull ;
225,6 → 226,7
GPIO_Init (GPIO2, &GPIO_InitStructure);
 
// SSP0_MISO pin GPIO2.6
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Direction = GPIO_PinOutput;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull ;
255,33 → 257,21
VIC_Config(SSP0_ITLine, VIC_IRQ, 1);
VIC_ITCmd(SSP0_ITLine, ENABLE);
 
SerialPutString("ok\n\r");
SerialPutString("ok");
}
 
//------------------------------------------------------
void SPI_CheckSlaveSelect(void)
{
DebugOut.Analog[0] = FromFlightCtrl.IntegralNick;
DebugOut.Analog[1] = FromFlightCtrl.IntegralRoll;
DebugOut.Analog[2] = (30*FromFlightCtrl.AccNick)/108;
DebugOut.Analog[3] = (30*FromFlightCtrl.AccRoll)/108;
DebugOut.Analog[25] = FromFlightCtrl.GyroHeading;
}
 
//------------------------------------------------------
void UpdateSPI_Buffer(void)
{
if (SPI_RxBuffer_Request)
{
if (CompassUpdateActiv) return; // testweise deaktiviert
 
// avoid sending data via SPI during the update of the ToFlightCtrl structure
VIC_ITCmd(SSP0_ITLine, DISABLE); // disable SPI interrupt
 
ToFlightCtrl.CompassHeading = I2C_Heading.Heading;
ToFlightCtrl.GPS_Nick = GPSStick.Nick;
ToFlightCtrl.GPS_Roll = GPSStick.Roll;
ToFlightCtrl.GPS_Yaw = GPSStick.Yaw;
ToFlightCtrl.GPS_Nick = GPS_Stick.Nick;
ToFlightCtrl.GPS_Roll = GPS_Stick.Roll;
ToFlightCtrl.GPS_Yaw = GPS_Stick.Yaw;
DebugOut.Analog[26] = I2C_Heading.Heading;
// cycle spi commands
ToFlightCtrl.Command = SPI_CommandSequence[SPI_CommandCounter++];
300,8 → 290,24
break;
 
case SPI_CMD_GPS_TARGET:
ToFlightCtrl.Param.Long[0] = GPSTargetPosition.Longitude;
ToFlightCtrl.Param.Long[1] = GPSTargetPosition.Latitude;
if(pTargetPosition != NULL)
{
if(pTargetPosition->Status != INVALID)
{
ToFlightCtrl.Param.Long[0] = pTargetPosition->Longitude;
ToFlightCtrl.Param.Long[1] = pTargetPosition->Latitude;
}
else
{
ToFlightCtrl.Param.Long[0] = 0;
ToFlightCtrl.Param.Long[1] = 0;
}
}
else
{
ToFlightCtrl.Param.Long[0] = 0;
ToFlightCtrl.Param.Long[1] = 0;
}
break;
 
default:
309,7 → 315,7
}
VIC_ITCmd(SSP0_ITLine, ENABLE); // enable SPI interrupt
 
if (I2C_Heading.Heading <= 359)
/* if (I2C_Heading.Heading <= 359)
{
// nothing?
}
317,7 → 323,7
{
if (I2C_Version.Major != 0xFF) TimerCompassUpdate = SetDelay(1);
return;
}
}*/
 
switch(FromFlightCtrl.Command)
{
330,9 → 336,31
Parameter.User6 = FromFlightCtrl.Param.Byte[5];
Parameter.User7 = FromFlightCtrl.Param.Byte[6];
Parameter.User8 = FromFlightCtrl.Param.Byte[7];
if(ClearMKFlags)
{
FC.MKFlags = 0;
ClearMKFlags = 0;
}
FC.MKFlags |= FromFlightCtrl.Param.Byte[8];
FC.UBat = FromFlightCtrl.Param.Byte[9];
Parameter.LowVoltageWarning = FromFlightCtrl.Param.Byte[10];
Parameter.ActiveSetting = FromFlightCtrl.Param.Byte[11];
break;
 
case SPI_CMD_PARAMETER1:
Parameter.NaviGpsModeControl = FromFlightCtrl.Param.Byte[0];
Parameter.NaviGpsGain = FromFlightCtrl.Param.Byte[1];
Parameter.NaviGpsP = FromFlightCtrl.Param.Byte[2];
Parameter.NaviGpsI = FromFlightCtrl.Param.Byte[3];
Parameter.NaviGpsD = FromFlightCtrl.Param.Byte[4];
Parameter.NaviGpsACC = FromFlightCtrl.Param.Byte[5];
Parameter.NaviGpsMinSat = FromFlightCtrl.Param.Byte[6];
Parameter.NaviStickThreshold = FromFlightCtrl.Param.Byte[7];
Parameter.NaviRadiusAlert = FromFlightCtrl.Param.Byte[8];
break;
 
case SPI_CMD_STICK:
FC.StickGas = FromFlightCtrl.Param.sByte[0];
FC.StickGas = FromFlightCtrl.Param.sByte[0];
FC.StickYaw = FromFlightCtrl.Param.sByte[1];
FC.StickRoll = FromFlightCtrl.Param.sByte[2];
FC.StickNick = FromFlightCtrl.Param.sByte[3];
341,7 → 369,6
FC.Poti3 = FromFlightCtrl.Param.Byte[6];
FC.Poti4 = FromFlightCtrl.Param.Byte[7];
FC.RC_Quality = FromFlightCtrl.Param.Byte[8];
FC.MotorsOn = FromFlightCtrl.Param.Byte[9];
break;
 
case SPI_CMD_CAL_COMPASS:
358,9 → 385,17
I2C_WriteAttitude.Nick = FromFlightCtrl.IntegralNick;
 
// every time we got new data from the FC via SPI call the navigation routine
Navigation();
GPS_Navigation();
ClearMKFlags = 1;
 
SPI_RxBuffer_Request = 0;
 
DebugOut.Analog[0] = FromFlightCtrl.IntegralNick;
DebugOut.Analog[1] = FromFlightCtrl.IntegralRoll;
DebugOut.Analog[2] = (30*FromFlightCtrl.AccNick)/108;
DebugOut.Analog[3] = (30*FromFlightCtrl.AccRoll)/108;
DebugOut.Analog[25] = FromFlightCtrl.GyroHeading;
 
}
}
 
/branches/V0.1 killagreg/spi_slave.h
1,14 → 1,14
#ifndef _SPI_SLAVE_H
#define _SPI_SLAVE_H
 
#define SS_PIN GPIO_ReadBit(GPIO2, GPIO_Pin_7)
 
#define SPI_PROTOCOL_COMP 1
 
 
#define SS_PIN GPIO_ReadBit(GPIO2, GPIO_Pin_7)
 
#define SPI_CMD_USER 10
#define SPI_CMD_STICK 11
#define SPI_CMD_CAL_COMPASS 12
#define SPI_CMD_PARAMETER1 13
 
typedef struct
{
44,7 → 44,7
s16 GPS_Yaw;
s16 CompassHeading;
s16 Status;
u8 BeepTime;
u16 BeepTime;
union
{
s8 sByte[12];
56,11 → 56,10
u8 Chksum;
} __attribute__((packed)) ToFlightCtrl_t;
 
extern FromFlightCtrl_t FromFlightCtrl;
extern ToFlightCtrl_t ToFlightCtrl;
extern volatile FromFlightCtrl_t FromFlightCtrl;
extern volatile ToFlightCtrl_t ToFlightCtrl;
 
extern void SPI0_Init(void);
extern void SPI_CheckSlaveSelect(void);
extern void UpdateSPI_Buffer(void);
 
#endif //_SPI_SLAVE_H
/branches/V0.1 killagreg/ssc.c
126,6 → 126,7
// enable APB clock for SPI1
SCU_APBPeriphClockConfig(__SSP1 ,ENABLE);
// configure P5.4 -> SD-CS as an output pin
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Direction = GPIO_PinOutput;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull ;
133,6 → 134,7
GPIO_InitStructure.GPIO_Alternate = GPIO_OutputAlt1;
GPIO_Init (GPIO5, &GPIO_InitStructure);
// configure P3.4 -> SCK1 and P3.6 -> MOSI1 as an output pin
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Direction = GPIO_PinOutput;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_6;
GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull ;
140,6 → 142,7
GPIO_InitStructure.GPIO_Alternate = GPIO_OutputAlt2;
GPIO_Init (GPIO3, &GPIO_InitStructure);
// configure P3.5 <- MISO1 as an input pin
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Direction = GPIO_PinInput;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull;
/branches/V0.1 killagreg/ssc.h
2,7 → 2,6
#define _SSC_H
 
 
#include "91x_lib.h"
//________________________________________________________________________________________________________________________________________
//
// Functions needed for accessing the sdcard low level via SPI.
/branches/V0.1 killagreg/timer.c
56,7 → 56,7
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#include "91x_lib.h"
#include "timer.h"
#include "uart.h"
#include "uart1.h"
 
u32 CountMilliseconds;
DateTime_t SystemTime;
64,11 → 64,14
//----------------------------------------------------------------------------------------------------
void TIM1_IRQHandler(void)
{
TIM1->OC1R += 200; // Timerfreq is 200kHz, generate an interrupt every 1ms
 
CountMilliseconds++;
//if (GPIO_ReadBit(GPIO6, GPIO_Pin_3)) GPIO_WriteBit(GPIO6, GPIO_Pin_3, Bit_RESET); else GPIO_WriteBit(GPIO6, GPIO_Pin_3, Bit_SET);
TIM_ClearFlag(TIM1, TIM_FLAG_OC1); // clear irq pending bit
TIM_ClearFlag(TIM1, TIM_FLAG_OC1); // clear irq pending bit
TIM1->OC1R += 200; // Timerfreq is 200kHz, generate an interrupt every 1ms
CountMilliseconds++;
//if (GPIO_ReadBit(GPIO6, GPIO_Pin_3)) GPIO_WriteBit(GPIO6, GPIO_Pin_3, Bit_RESET); else GPIO_WriteBit(GPIO6, GPIO_Pin_3, Bit_SET);
// write any value to VIC0 Vector address register
VIC0->VAR = 0xFF;
}
 
//----------------------------------------------------------------------------------------------------
/branches/V0.1 killagreg/timer.h
1,6 → 1,7
#ifndef _TIMER_H
#define _TIMER_H
 
 
typedef struct{
u16 Year;
u8 Month;
/branches/V0.1 killagreg/uart0.c
0,0 → 1,267
/*#######################################################################################*/
/* !!! THIS IS NOT FREE SOFTWARE !!! */
/*#######################################################################################*/
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Copyright (c) 2008 Ingo Busker, Holger Buss
// + Nur für den privaten Gebrauch
// + FOR NON COMMERCIAL USE ONLY
// + 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 (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 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 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 permitted
// + 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
// + * If sources or documentations are redistributet on other webpages, out webpage (http://www.MikroKopter.de) must be
// + clearly linked as origin
// + * PORTING this software (or part of it) 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.
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//#include <stdio.h>
#include "91x_lib.h"
#include "uart1.h"
#include "ubx.h"
 
//------------------------------------------------------------------------------------
// global variables
 
// UART0 MUXER
typedef enum
{
UART0_UNDEF,
UART0_MK3MAG,
UART0_MKGPS
} UART0_MuxerState_t;
 
UART0_MuxerState_t UART0_Muxer = UART0_UNDEF;
 
//------------------------------------------------------------------------------------
// functions
 
/********************************************************/
/* Connect RXD & TXD to GPS */
/********************************************************/
void UART0_Connect_to_MKGPS(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
 
UART0_Muxer = UART0_UNDEF;
 
SCU_APBPeriphClockConfig(__GPIO6, ENABLE); // Enable the GPIO6 Clock
// unmap UART0 from Compass
// set port pin 5.1 (serial data from compass) to input and disconnect from IP
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Direction = GPIO_PinInput;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull ;
GPIO_InitStructure.GPIO_IPConnected = GPIO_IPConnected_Disable;
GPIO_InitStructure.GPIO_Alternate = GPIO_InputAlt1;
GPIO_Init(GPIO5, &GPIO_InitStructure);
// set port pin 5.0 (serial data to compass) to input
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Direction = GPIO_PinInput;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull;
GPIO_InitStructure.GPIO_IPConnected = GPIO_IPConnected_Disable;
GPIO_InitStructure.GPIO_Alternate = GPIO_InputAlt1;
GPIO_Init(GPIO5, &GPIO_InitStructure);
// map UART0 to GPS
// set port pin 6.6 (serial data from gps) to input and connect to IP
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Direction = GPIO_PinInput;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull ;
GPIO_InitStructure.GPIO_IPConnected = GPIO_IPConnected_Enable;
GPIO_InitStructure.GPIO_Alternate = GPIO_InputAlt1; //UART0_RxD
GPIO_Init(GPIO6, &GPIO_InitStructure);
// set port pin 6.7 (serial data to gps) to output
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Direction = GPIO_PinOutput;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull;
GPIO_InitStructure.GPIO_IPConnected = GPIO_IPConnected_Enable;
GPIO_InitStructure.GPIO_Alternate = GPIO_OutputAlt3; //UART0_TX
GPIO_Init(GPIO6, &GPIO_InitStructure);
UART0_Muxer = UART0_MKGPS;
}
 
/********************************************************/
/* Connect RXD & TXD to MK3MAG */
/********************************************************/
void UART0_Connect_to_MK3MAG(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
 
UART0_Muxer = UART0_UNDEF;
 
SCU_APBPeriphClockConfig(__GPIO5, ENABLE);
// unmap UART0 from GPS
// set port pin 6.6 (serial data from gps) to input and disconnect from IP
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Direction = GPIO_PinInput;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull;
GPIO_InitStructure.GPIO_IPConnected = GPIO_IPConnected_Disable;
GPIO_InitStructure.GPIO_Alternate = GPIO_InputAlt1;
GPIO_Init(GPIO6, &GPIO_InitStructure);
// set port pin 6.7 (serial data to gps) to input
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Direction = GPIO_PinInput;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull;
GPIO_InitStructure.GPIO_IPConnected = GPIO_IPConnected_Disable;
GPIO_InitStructure.GPIO_Alternate = GPIO_InputAlt1;
GPIO_Init(GPIO6, &GPIO_InitStructure);
 
// map UART0 to Compass
// set port pin 5.1 (serial data from compass) to input and connect to IP
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Direction = GPIO_PinInput;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull ;
GPIO_InitStructure.GPIO_IPConnected = GPIO_IPConnected_Enable;
GPIO_InitStructure.GPIO_Alternate = GPIO_InputAlt1; //UART0_RxD
GPIO_Init(GPIO5, &GPIO_InitStructure);
// set port pin 5.0 (serial data to compass) to output
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Direction = GPIO_PinOutput;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull;
GPIO_InitStructure.GPIO_IPConnected = GPIO_IPConnected_Enable;
GPIO_InitStructure.GPIO_Alternate = GPIO_OutputAlt3; //UART0_TX
GPIO_Init(GPIO5, &GPIO_InitStructure);
 
UART0_Muxer = UART0_MK3MAG;
}
 
/********************************************************/
/* Initialize UART0 */
/********************************************************/
void UART0_Init(void)
{
UART_InitTypeDef UART_InitStructure;
SerialPutString("\r\n UART0 init...");
 
SCU_APBPeriphClockConfig(__UART0, ENABLE); // Enable the UART0 Clock
 
UART0_Connect_to_MKGPS(); // to GPS serial interface
 
/* UART0 configured as follow:
- Word Length = 8 Bits
- One Stop Bit
- No parity
- BaudRate = 57600 baud
- Hardware flow control Disabled
- Receive and transmit enabled
- Receive and transmit FIFOs are Disabled
*/
UART_StructInit(&UART_InitStructure);
UART_InitStructure.UART_WordLength = UART_WordLength_8D;
UART_InitStructure.UART_StopBits = UART_StopBits_1;
UART_InitStructure.UART_Parity = UART_Parity_No ;
UART_InitStructure.UART_BaudRate = BAUD_RATE;
UART_InitStructure.UART_HardwareFlowControl = UART_HardwareFlowControl_None;
UART_InitStructure.UART_Mode = UART_Mode_Tx_Rx;
UART_InitStructure.UART_FIFO = UART_FIFO_Enable;
UART_InitStructure.UART_TxFIFOLevel = UART_FIFOLevel_1_2;
UART_InitStructure.UART_RxFIFOLevel = UART_FIFOLevel_1_2;
 
UART_DeInit(UART0); // reset uart 0 to default
UART_Init(UART0, &UART_InitStructure); // initialize uart 0
 
// enable uart 0 interrupts selective
UART_ITConfig(UART0, UART_IT_Receive | UART_IT_ReceiveTimeOut, ENABLE);
UART_Cmd(UART0, ENABLE); // enable uart 0
// configure the uart 0 interupt line as an IRQ with priority 10 (0 is highest)
VIC_Config(UART0_ITLine, VIC_IRQ, 10);
// enable the uart 0 IRQ
VIC_ITCmd(UART0_ITLine, ENABLE);
 
SerialPutString("ok");
}
 
/********************************************************/
/* UART0 Interrupt Handler */
/********************************************************/
void UART0_IRQHandler(void)
{
u8 c;
// if receive irq or receive timeout irq has occured
if((UART_GetITStatus(UART0, UART_IT_Receive) != RESET) || (UART_GetITStatus(UART0, UART_IT_ReceiveTimeOut) != RESET) )
{
UART_ClearITPendingBit(UART0, UART_IT_Receive); // clear receive interrupt flag
UART_ClearITPendingBit(UART0, UART_IT_ReceiveTimeOut); // clear receive timeout interrupt flag
 
// if debug UART is UART0
if (DebugUART == UART0)
{ // forward received data to the UART1 tx buffer
while(UART_GetFlagStatus(UART0, UART_FLAG_RxFIFOEmpty) != SET)
{
// wait for space in the tx buffer of the UART1
while(UART_GetFlagStatus(UART1, UART_FLAG_TxFIFOFull) == SET) {};
// move the byte from the rx buffer of UART0 to the tx buffer of UART1
UART_SendData(UART1, UART_ReceiveData(UART0));
}
}
else // UART0 is not the DebugUART (normal operation)
{
// repeat until no byte is in the RxFIFO
while (UART_GetFlagStatus(UART0, UART_FLAG_RxFIFOEmpty) != SET)
{
c = UART_ReceiveData(UART0); // get byte from rx fifo
switch(UART0_Muxer)
{
case UART0_MKGPS:
UBX_Parser(c); // if connected to GPS forward byte to ubx parser
break;
case UART0_MK3MAG:
// ignora any byte send from MK3MAG
break;
case UART0_UNDEF:
default:
// ignore the byte from unknown source
break;
} // eof switch(UART0_Muxer)
} // eof while
} // eof UART0 is not the DebugUART
} // eof receive irq or receive timeout irq
}
/branches/V0.1 killagreg/uart0.h
0,0 → 1,9
#ifndef __UART0_H
#define __UART0_H
 
void UART0_Init (void);
void UART0_Connect_to_MKGPS(void);
void UART0_Connect_to_MK3MAG(void);
 
#endif //__UART0_H
 
/branches/V0.1 killagreg/uart1.c
0,0 → 1,552
/*#######################################################################################*/
/* !!! THIS IS NOT FREE SOFTWARE !!! */
/*#######################################################################################*/
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Copyright (c) 2008 Ingo Busker, Holger Buss
// + Nur für den privaten Gebrauch
// + FOR NON COMMERCIAL USE ONLY
// + 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 (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 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 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 permitted
// + 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
// + * If sources or documentations are redistributet on other webpages, out webpage (http://www.MikroKopter.de) must be
// + clearly linked as origin
// + * PORTING this software (or part of it) 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.
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#include "91x_lib.h"
#include "ramfunc.h"
#include "menu.h"
#include "printf_P.h"
#include "GPS.h"
#include "uart0.h"
#include "uart1.h"
//#include "uart2.h"
#include "timer.h"
#include "usb.h"
#include "main.h"
 
#define FALSE 0
#define TRUE 1
 
u8 Request_VerInfo = FALSE;
u8 Request_ExternalControl = FALSE;
u8 Request_Display = FALSE;
u8 Request_DebugData = FALSE;
u8 Request_DebugLabel = 255;
u8 Request_ChannelOnly = FALSE;
u8 Request_GPS_Position = FALSE;
u8 Remote_PollDisplayLine = 0;
 
UART_TypeDef *DebugUART = UART1;
 
volatile u8 txd_buffer[TXD_BUFFER_LEN];
volatile u8 rxd_buffer_locked = FALSE;
volatile u8 rxd_buffer[RXD_BUFFER_LEN];
volatile u8 txd_complete = TRUE;
volatile u8 ReceivedBytes = 0;
 
volatile u8 CntCrcError = 0;
u8 text[50];
 
u8 PcAccess = 100;
u8 MotorTest[4] = {0,0,0,0};
u8 MySlaveAddr = 0;
u8 ConfirmFrame;
 
DebugOut_t DebugOut;
ExternControl_t ExternControl;
VersionInfo_t VersionInfo;
GPSPosition_t GPS_Position;
 
s32 Debug_Timer;
 
static u16 ptr_txd_buffer = 0;
 
const u8 ANALOG_LABEL[32][16] =
{
//1234567890123456
"AngleNick ", //0
"AngleRoll ",
"AccNick ",
"AccRoll ",
" ",
" ", //5
" ",
" ",
" ",
" ",
" ", //10
" ",
"SPI Error ",
"SPI Okay ",
" ",
" ", //15
"I2C_ReadByte ",
"ACC_Speed_N ",
"ACC_Speed_E ",
" ",
" ", //20
"N_Speed ",
"E_Speed ",
"KalmDist_N ",
"KalmDist_E ",
"GyroHeading ", //25
"CompassHeading ",
"Distance N ",
"Distance E ",
"GPS_Nick ",
"GPS_Roll ", //30
"Used_Sats "
};
 
 
/********************************************************/
/* Initialization the UART1 */
/********************************************************/
void UART1_Init (void)
{
GPIO_InitTypeDef GPIO_InitStructure;
UART_InitTypeDef UART_InitStructure;
 
SCU_APBPeriphClockConfig(__UART1, ENABLE); // Enable the UART1 Clock
SCU_APBPeriphClockConfig(__GPIO3, ENABLE); // Enable the GPIO3 Clock
 
/*Configure UART1_Rx pin GPIO3.2*/
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Direction = GPIO_PinInput;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull;
GPIO_InitStructure.GPIO_IPConnected = GPIO_IPConnected_Enable;
GPIO_InitStructure.GPIO_Alternate = GPIO_InputAlt1; // UART1_RxD
GPIO_Init(GPIO3, &GPIO_InitStructure);
 
/*Configure UART1_Tx pin GPIO3.3*/
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Direction = GPIO_PinOutput;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull;
GPIO_InitStructure.GPIO_Alternate = GPIO_OutputAlt2; // UART1_TX
GPIO_Init(GPIO3, &GPIO_InitStructure);
 
/* UART1 configured as follow:
- Word Length = 8 Bits
- One Stop Bit
- No parity
- BaudRate = 57600 baud
- Hardware flow control Disabled
- Receive and transmit enabled
- Receive and transmit FIFOs are Disabled
*/
UART_StructInit(&UART_InitStructure);
UART_InitStructure.UART_WordLength = UART_WordLength_8D;
UART_InitStructure.UART_StopBits = UART_StopBits_1;
UART_InitStructure.UART_Parity = UART_Parity_No ;
UART_InitStructure.UART_BaudRate = BAUD_RATE;
UART_InitStructure. UART_HardwareFlowControl = UART_HardwareFlowControl_None;
UART_InitStructure.UART_Mode = UART_Mode_Tx_Rx;
UART_InitStructure.UART_FIFO = UART_FIFO_Enable;
UART_InitStructure.UART_TxFIFOLevel = UART_FIFOLevel_1_2;
UART_InitStructure.UART_RxFIFOLevel = UART_FIFOLevel_1_2;
 
UART_DeInit(UART1); // reset uart 1 to default
UART_Init(UART1, &UART_InitStructure); // initialize uart 1
// enable uart 1 interrupts selective
UART_ITConfig(UART1, UART_IT_Receive | UART_IT_ReceiveTimeOut, ENABLE);
UART_Cmd(UART1, ENABLE); // enable uart 1
// configure the uart 1 interupt line as an IRQ with priority 4 (0 is highest)
VIC_Config(UART1_ITLine, VIC_IRQ, 4);
// enable the uart 1 IRQ
VIC_ITCmd(UART1_ITLine, ENABLE);
// initialize the debug timer
Debug_Timer = SetDelay(3000);
// unlock rxd_buffer
rxd_buffer_locked = FALSE;
// no bytes to send
txd_complete = TRUE;
SerialPutString("\r\nUART1 init...ok");
}
 
 
/****************************************************************/
/* USART1 receiver ISR */
/****************************************************************/
void UART1_IRQHandler(void)
{
static u16 crc;
static u8 ptr_rxd_buffer = 0;
static u8 crc1, crc2;
u8 c;
 
if((UART_GetITStatus(UART1, UART_IT_Receive) != RESET) || (UART_GetITStatus(UART1, UART_IT_ReceiveTimeOut) != RESET) )
{
// clear the pending bits
UART_ClearITPendingBit(UART1, UART_IT_Receive);
UART_ClearITPendingBit(UART1, UART_IT_ReceiveTimeOut);
// if debug UART is not UART1
if (DebugUART != UART1)
{ // forward received data to the debug UART tx buffer
while(UART_GetFlagStatus(UART1, UART_FLAG_RxFIFOEmpty) != SET)
{
// wait for space in the tx buffer of the DebugUART
while(UART_GetFlagStatus(DebugUART, UART_FLAG_TxFIFOFull) == SET) {};
// move the byte from the rx buffer of UART1 to the tx buffer of DebugUART
UART_SendData(DebugUART, UART_ReceiveData(UART1));
}
}
else // DebugUART == UART1 (normal operation)
{
while ((UART_GetFlagStatus(UART1, UART_FLAG_RxFIFOEmpty) != SET) && (!rxd_buffer_locked))
{ // some byes in the fifo and rxd buffer not locked
// get byte from fifo
c = UART_ReceiveData(UART1);
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) // rxd buffer not full
{
if (c != '\r') // no termination character received
{
rxd_buffer[ptr_rxd_buffer++] = c; // copy byte to rxd buffer
crc += c; // update crc
}
else // termination character received
{
// the last 2 bytes are no subject for checksum calculation
// they are the checksum itself
crc -= rxd_buffer[ptr_rxd_buffer-2];
crc -= rxd_buffer[ptr_rxd_buffer-1];
// calculate checksum from transmitted data
crc %= 4096;
crc1 = '=' + crc / 64;
crc2 = '=' + crc % 64;
// compare checksum to transmitted checksum bytes
if((crc1 == rxd_buffer[ptr_rxd_buffer-2]) && (crc2 == rxd_buffer[ptr_rxd_buffer-1]))
{ // checksum valid
rxd_buffer_locked = TRUE; // lock the rxd buffer
ReceivedBytes = ptr_rxd_buffer; // store number of received bytes
rxd_buffer[ptr_rxd_buffer] = '\r'; // set termination character
// if 2nd byte is an 'R' start bootloader
if(rxd_buffer[2] == 'R')
{
PowerOff();
VIC_DeInit();
Execute_Bootloader(); // Reset-Commando - Bootloader starten
}
} // eof checksum valid
else
{ // checksum invalid
rxd_buffer_locked = FALSE; // unlock rxd buffer
} // eof checksum invalid
ptr_rxd_buffer = 0; // reset rxd buffer pointer
} // eof termination character received
} // rxd buffer not full
else // rxd buffer overrun
{
ptr_rxd_buffer = 0; // reset rxd buffer pointer
rxd_buffer_locked = FALSE; // unlock rxd buffer
} // eof rxd buffer overrrun
} // some byes in the fifo and rxd buffer not locked
} // eof DebugUart = UART1
}
}
 
/**************************************************************/
/* Transmit tx buffer via debug uart */
/**************************************************************/
void UART1_Transmit(void)
{
u8 tmp_tx;
// if something has to be send and the txd fifo is not full
if((!txd_complete) && (UART_GetFlagStatus(UART1, UART_FLAG_TxFIFOFull) == RESET))
{
tmp_tx = txd_buffer[ptr_txd_buffer]; // read byte from txd buffer
// if terminating character or end of txd buffer reached
if((tmp_tx == '\r') || (ptr_txd_buffer == TXD_BUFFER_LEN))
{
ptr_txd_buffer = 0; // reset txd buffer pointer
txd_complete = TRUE;// set complete flag
}
UART_SendData(UART1, tmp_tx); // put character to txd fifo
// set pointer to next byte
ptr_txd_buffer++;
}
}
 
/**************************************************************/
/* Add CRC and initiate transmission via debug uart */
/**************************************************************/
void AddCRC(u16 datalen)
{
u16 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';
 
ptr_txd_buffer = 0;
txd_complete = FALSE;
UART_SendData(UART1,txd_buffer[ptr_txd_buffer++]); // send first byte
}
 
 
 
/**************************************************************/
/* Code output data */
/**************************************************************/
void SendOutData(u8 cmd, u8 module, u8 *snd, u8 len)
{
u16 pt = 0;
u8 a,b,c;
u8 ptr = 0;
 
txd_buffer[pt++] = '#'; // Start character
txd_buffer[pt++] = module; // Address (a=0; b=1,...)
txd_buffer[pt++] = cmd; // Command
 
while(len)
{
if(len) { a = snd[ptr++]; len--;} else a = 0;
if(len) { b = snd[ptr++]; len--;} else b = 0;
if(len) { c = snd[ptr++]; len--;} else c = 0;
txd_buffer[pt++] = '=' + (a >> 2);
txd_buffer[pt++] = '=' + (((a & 0x03) << 4) | ((b & 0xf0) >> 4));
txd_buffer[pt++] = '=' + (((b & 0x0f) << 2) | ((c & 0xc0) >> 6));
txd_buffer[pt++] = '=' + ( c & 0x3f);
}
AddCRC(pt); // add checksum after data block and initates the transmission
}
 
 
/**************************************************************/
/* Decode data */
/**************************************************************/
void Decode64(u8 *ptrOut, u8 len, u8 ptrIn ,u8 max)
{
u8 a,b,c,d;
u8 ptr = 0;
u8 x,y,z;
while(len)
{
a = rxd_buffer[ptrIn++] - '=';
b = rxd_buffer[ptrIn++] - '=';
c = rxd_buffer[ptrIn++] - '=';
d = rxd_buffer[ptrIn++] - '=';
if(ptrIn > max - 2) break;
 
x = (a << 2) | (b >> 4);
y = ((b & 0x0f) << 4) | (c >> 2);
z = ((c & 0x03) << 6) | d;
 
if(len--) ptrOut[ptr++] = x; else break;
if(len--) ptrOut[ptr++] = y; else break;
if(len--) ptrOut[ptr++] = z; else break;
}
}
 
/**************************************************************/
/* Process incomming data from debug uart */
/**************************************************************/
void UART1_ProcessRxData(void)
{
// if data in the rxd buffer are not locked immediately return
if((!rxd_buffer_locked) || (DebugUART != UART1) ) return;
 
u8 tmp_char_arr2[2];
s32 tmp_long_arr3[2];
 
PcAccess = 255;
switch(rxd_buffer[2])
{
case 'a':// Labels of the Analog Debug outputs
Decode64((u8 *) &tmp_char_arr2[0], sizeof(tmp_char_arr2),3 ,ReceivedBytes);
Request_DebugLabel = tmp_char_arr2[0];
break;
case 'b': // extern control
Decode64((u8 *) &ExternControl, sizeof(ExternControl), 3 ,ReceivedBytes);
RemoteButtons |= ExternControl.RemoteButtons;
ConfirmFrame = ExternControl.Frame;
break;
case 'c': // extern control with debug request
Decode64((u8 *) &ExternControl, sizeof(ExternControl), 3, ReceivedBytes);
RemoteButtons |= ExternControl.RemoteButtons;
ConfirmFrame = ExternControl.Frame;
Request_DebugData = TRUE;
break;
case 'h':// x-1 display columns
Decode64((u8 *) &tmp_char_arr2[0], sizeof(tmp_char_arr2), 3, ReceivedBytes);
RemoteButtons |= tmp_char_arr2[0];
if(tmp_char_arr2[1] == 255) Request_ChannelOnly = 1; else Request_ChannelOnly = 0; // no displaydata
Request_Display = TRUE;
break;
case 's':// new GPSPCPosition
Decode64((unsigned char *) &tmp_long_arr3[0], sizeof(tmp_long_arr3), 3,ReceivedBytes);
GPSPCPosition.Status = INVALID;
GPSPCPosition.Longitude = tmp_long_arr3[0];
GPSPCPosition.Latitude = tmp_long_arr3[1];
GPSPCPosition.Altitude = 0;
GPSPCPosition.Status = NEWDATA;
break;
case 'v': // get version
Request_VerInfo = TRUE;
break;
case 'g':// get external control data
Request_ExternalControl = TRUE;
break;
case 'u':
Decode64((unsigned char *) &tmp_char_arr2[0], sizeof(tmp_char_arr2), 3,ReceivedBytes);
switch(tmp_char_arr2[0])
{
case UART_FLIGHTCTRL:
//UART2_Init(); // initialize UART2 to FC pins
//DebugUART = UART2;
break;
case UART_MK3MAG:
UART0_Connect_to_MK3MAG(); // mux UART0 to MK3MAG pins
DebugUART = UART0;
break;
case UART_MKGPS:
UART0_Connect_to_MKGPS(); // connect UART0 to MKGPS pins
DebugUART = UART0;
break;
}
break;
case 'l':
case 'm':
case 'n':
case 'o':
case 'p':
break;
}
// unlock the rxd buffer after processing
rxd_buffer_locked = FALSE;
}
 
 
/*****************************************************/
/* Send a character */
/*****************************************************/
s16 uart_putchar (char c)
{
if (c == '\n')
uart_putchar('\r');
// wait until txd fifo is not full
while (UART_GetFlagStatus(UART1, UART_FLAG_TxFIFOFull) != RESET);
// transmit byte
UART_SendData(UART1, c);
return (0);
}
 
/*****************************************************/
/* Send a sting to the debug uart */
/*****************************************************/
void SerialPutString(u8 *s)
{
while (*s != '\0')
{
uart_putchar(*s);
s ++;
}
}
 
 
 
/**************************************************************/
/* Send the answers to incomming commands at the debug uart */
/**************************************************************/
void UART1_TransmitTxData(void)
{
if(!txd_complete || (DebugUART != UART1) ) return;
 
if(Request_ExternalControl && txd_complete) // Bei Get werden die vom PC einstellbaren Werte vom PC zurückgelesen
{
SendOutData('G',MySlaveAddr,(u8 *) &ExternControl,sizeof(ExternControl));
Request_ExternalControl = FALSE;
}
if((CheckDelay(Debug_Timer) || Request_DebugData) && txd_complete)
{
SendOutData('D',MySlaveAddr,(u8 *) &DebugOut,sizeof(DebugOut));
Request_DebugData = FALSE;
Debug_Timer = SetDelay(2000);
}
if(Request_DebugLabel != 255) // Texte für die Analogdaten
{
SendOutData('A',Request_DebugLabel + '0',(u8 *) ANALOG_LABEL[Request_DebugLabel],16);
Request_DebugLabel = 255;
}
if(Request_Display && txd_complete)
{
LCD_PrintMenu();
Request_Display = FALSE;
if(++Remote_PollDisplayLine == 4 || Request_ChannelOnly)
{
SendOutData('4',0,(u8 *) &VersionInfo,sizeof(VersionInfo)); // DisplayZeile übertragen
Remote_PollDisplayLine = -1;
}
else SendOutData('0' + Remote_PollDisplayLine,0,(u8 *)&DisplayBuff[20 * Remote_PollDisplayLine],20); // DisplayZeile übertragen
}
if(Request_VerInfo && txd_complete)
{
SendOutData('V',MySlaveAddr,(u8 *) &VersionInfo,sizeof(VersionInfo));
Request_VerInfo = FALSE;
}
if(Request_GPS_Position && txd_complete)
{
SendOutData('Q',MySlaveAddr,(u8 *) &GPS_Position,sizeof(GPS_Position));
Request_GPS_Position = FALSE;
}
}
 
/branches/V0.1 killagreg/uart1.h
0,0 → 1,74
#ifndef _UART1_H
#define _UART1_H
 
#define UART_FLIGHTCTRL 0
#define UART_MK3MAG 1
#define UART_MKGPS 2
 
#define TXD_BUFFER_LEN 150
#define RXD_BUFFER_LEN 150
#define BAUD_RATE 57600 //Baud Rate for the serial interfaces
 
typedef struct
{
u8 Digital[2];
u16 Analog[32]; // Debugwerte
} __attribute__((packed)) DebugOut_t;
 
extern DebugOut_t DebugOut;
 
typedef struct
{
u8 Digital[2];
u8 RemoteButtons;
s8 Nick;
s8 Roll;
s8 Yaw;
u8 Gas;
s8 Height;
u8 free;
u8 Frame;
u8 Config;
} __attribute__((packed)) ExternControl_t;
 
extern ExternControl_t ExternControl;
 
typedef struct GPSPosition
{
s32 Longitude;
s32 Latitude;
s32 TargetLongitude;
s32 TargetLatitude;
s32 Distance2Target;
s32 Angle2Target;
u8 Used_Sat;
} __attribute__((packed)) GPSPosition_t;
 
extern u8 Request_GPS_Position;
extern GPSPosition_t GPS_Position;
 
typedef struct
{
u8 Major;
u8 Minor;
u8 Patch;
u8 Reserved[7];
} __attribute__((packed)) VersionInfo_t;
 
extern VersionInfo_t VersionInfo;
extern volatile u8 rxd_buffer[RXD_BUFFER_LEN];
extern volatile u8 ReceivedBytes;
extern volatile u8 rxd_buffer_locked;
extern UART_TypeDef *DebugUART;
 
 
void UART1_Init(void);
void UART1_Transmit(void);
void UART1_TransmitTxData(void);
void UART1_ProcessRxData(void);
 
extern s16 uart_putchar (char c);
extern void SerialPutString(u8 *s);
extern u8 text[50];
 
#endif //_UART1_H
/branches/V0.1 killagreg/uart2.c
0,0 → 1,156
/*#######################################################################################*/
/* !!! THIS IS NOT FREE SOFTWARE !!! */
/*#######################################################################################*/
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Copyright (c) 2008 Ingo Busker, Holger Buss
// + Nur für den privaten Gebrauch
// + FOR NON COMMERCIAL USE ONLY
// + 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 (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 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 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 permitted
// + 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
// + * If sources or documentations are redistributet on other webpages, out webpage (http://www.MikroKopter.de) must be
// + clearly linked as origin
// + * PORTING this software (or part of it) 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.
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//#include <stdio.h>
#include "91x_lib.h"
#include "uart1.h"
 
/********************************************************/
/* Initialize UART2 */
/********************************************************/
void UART2_Init(void)
{
UART_InitTypeDef UART_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
 
SerialPutString("\r\n UART2 init...");
 
SCU_APBPeriphClockConfig(__UART2, ENABLE); // Enable the UART2 Clock
SCU_APBPeriphClockConfig(__GPIO5, ENABLE); // Enable the GPIO5 Clock
/*Configure UART2_Rx pin GPIO5.2*/
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Direction = GPIO_PinInput;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull;
GPIO_InitStructure.GPIO_IPConnected = GPIO_IPConnected_Enable;
GPIO_InitStructure.GPIO_Alternate = GPIO_InputAlt1; // UART2_RxD
GPIO_Init(GPIO5, &GPIO_InitStructure);
 
SCU_APBPeriphClockConfig(__GPIO3, ENABLE); // Enable the GPIO3 Clock
/*Configure UART2_Tx pin GPIO3.0*/
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Direction = GPIO_PinOutput;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull;
GPIO_InitStructure.GPIO_Alternate = GPIO_OutputAlt2; // UART2_TX
GPIO_Init(GPIO3, &GPIO_InitStructure);
 
 
/* UART2 configured as follow:
- Word Length = 8 Bits
- One Stop Bit
- No parity
- BaudRate = 57600 baud
- Hardware flow control Disabled
- Receive and transmit enabled
- Receive and transmit FIFOs are Disabled
*/
UART_StructInit(&UART_InitStructure);
UART_InitStructure.UART_WordLength = UART_WordLength_8D;
UART_InitStructure.UART_StopBits = UART_StopBits_1;
UART_InitStructure.UART_Parity = UART_Parity_No ;
UART_InitStructure.UART_BaudRate = BAUD_RATE;
UART_InitStructure.UART_HardwareFlowControl = UART_HardwareFlowControl_None;
UART_InitStructure.UART_Mode = UART_Mode_Tx_Rx;
UART_InitStructure.UART_FIFO = UART_FIFO_Enable;
UART_InitStructure.UART_TxFIFOLevel = UART_FIFOLevel_1_2;
UART_InitStructure.UART_RxFIFOLevel = UART_FIFOLevel_1_2;
 
UART_DeInit(UART2); // reset uart 0 to default
UART_Init(UART2, &UART_InitStructure); // initialize uart 0
 
// enable uart 2 interrupts selective
UART_ITConfig(UART2, UART_IT_Receive | UART_IT_ReceiveTimeOut, ENABLE);
UART_Cmd(UART2, ENABLE); // enable uart 0
// configure the uart 2 interupt line as an IRQ with priority 9 (0 is highest)
VIC_Config(UART2_ITLine, VIC_IRQ, 9);
// enable the uart 2 IRQ
VIC_ITCmd(UART2_ITLine, ENABLE);
 
SerialPutString("ok");
}
 
/********************************************************/
/* UART2 Interrupt Handler */
/********************************************************/
void UART2_IRQHandler(void)
{
// if receive irq or receive timeout irq has occured
if((UART_GetITStatus(UART2, UART_IT_Receive) != RESET) || (UART_GetITStatus(UART2, UART_IT_ReceiveTimeOut) != RESET) )
{
UART_ClearITPendingBit(UART2, UART_IT_Receive); // clear receive interrupt flag
UART_ClearITPendingBit(UART2, UART_IT_ReceiveTimeOut); // clear receive timeout interrupt flag
 
// if debug UART is UART2
if (DebugUART == UART2)
{ // forward received data to the UART1 tx buffer
while(UART_GetFlagStatus(UART2, UART_FLAG_RxFIFOEmpty) != SET)
{
// wait for space in the tx buffer of the UART1
while(UART_GetFlagStatus(UART1, UART_FLAG_TxFIFOFull) == SET) {};
// move the byte from the rx buffer of UART0 to the tx buffer of UART1
UART_SendData(UART1, UART_ReceiveData(UART2));
}
}
else
{
// ignore serial data from the FC
while(UART_GetFlagStatus(UART2, UART_FLAG_RxFIFOEmpty) != SET)
UART_ReceiveData(UART2);
}
} // eof receive irq or receive timeout irq
}
/branches/V0.1 killagreg/uart2.h
0,0 → 1,6
#ifndef __UART2_H
#define __UART2_H
 
void UART2_Init (void);
 
#endif //__UART2_H
/branches/V0.1 killagreg/ubx.c
0,0 → 1,434
/*#######################################################################################*/
/* !!! THIS IS NOT FREE SOFTWARE !!! */
/*#######################################################################################*/
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Copyright (c) 2008 Ingo Busker, Holger Buss
// + Nur für den privaten Gebrauch
// + FOR NON COMMERCIAL USE ONLY
// + 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 (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 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 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 permitted
// + 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
// + * If sources or documentations are redistributet on other webpages, out webpage (http://www.MikroKopter.de) must be
// + clearly linked as origin
// + * PORTING this software (or part of it) 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.
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#include "91x_lib.h"
#include "uart1.h"
#include "ubx.h"
#include "led.h"
#include "timer.h"
 
// ------------------------------------------------------------------------------------------------
// defines
 
#define DAYS_FROM_JAN01YEAR0001_TO_JAN6_1980 722819 // the year 0 does not exist!
#define DAYS_PER_YEAR 365
#define DAYS_PER_LEAPYEAR 366
#define DAYS_PER_4YEARS 1461 //((3 * DAYS_PER_YEAR) + DAYS_PER_LEAPYEAR) // years dividable by 4 are leap years
#define DAYS_PER_100YEARS 36524 //((25 * DAYS_PER_4YEARS) - 1) // years dividable by 100 are no leap years
#define DAYS_PER_400YEARS 146097 //((4 * DAYS_PER_100YEARS) + 1L) // but years dividable by 400 are leap years
#define SECONDS_PER_MINUTE 60
#define MINUTES_PER_HOUR 60
#define HOURS_PER_DAY 24
#define DAYS_PER_WEEK 7
#define SECONDS_PER_HOUR 3600 //(SECONDS_PER_MINUTE * MINUTES_PER_HOUR)
#define SECONDS_PER_DAY 86400 //(SECONDS_PER_HOUR * HOURS_PER_DAY)
#define SECONDS_PER_WEEK 604800 //(SECONDS_PER_DAY * DAYS_PER_WEEK)
 
 
const u32 Leap[ 13 ] = { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 };
const u32 Normal[ 13 ] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
 
#define LEAP_SECONDS_FROM_1980 13
 
// message sync bytes
#define UBX_SYNC1_CHAR 0xB5
#define UBX_SYNC2_CHAR 0x62
// protocoll identifier
#define UBX_CLASS_NAV 0x01
// message id
#define UBX_ID_POSLLH 0x02
#define UBX_ID_SOL 0x06
#define UBX_ID_VELNED 0x12
 
// ------------------------------------------------------------------------------------------------
// typedefs
 
 
// ubx parser state
typedef enum
{
UBXSTATE_IDLE,
UBXSTATE_SYNC1,
UBXSTATE_SYNC2,
UBXSTATE_CLASS,
UBXSTATE_LEN1,
UBXSTATE_LEN2,
UBXSTATE_DATA,
UBXSTATE_CKA,
UBXSTATE_CKB
} ubxState_t;
 
typedef struct
{
u32 itow; // ms GPS Millisecond Time of Week
s32 frac; // ns remainder of rounded ms above
s16 week; // GPS week
u8 GPSfix; // GPSfix Type, range 0..6
u8 Flags; // Navigation Status Flags
s32 ECEF_X; // cm ECEF X coordinate
s32 ECEF_Y; // cm ECEF Y coordinate
s32 ECEF_Z; // cm ECEF Z coordinate
u32 PAcc; // cm 3D Position Accuracy Estimate
s32 ECEFVX; // cm/s ECEF X velocity
s32 ECEFVY; // cm/s ECEF Y velocity
s32 ECEFVZ; // cm/s ECEF Z velocity
u32 SAcc; // cm/s Speed Accuracy Estimate
u16 PDOP; // 0.01 Position DOP
u8 res1; // reserved
u8 numSV; // Number of SVs used in navigation solution
u32 res2; // reserved
Status_t Status; // invalid/newdata/processed
} __attribute__((packed)) ubx_nav_sol_t;
 
 
typedef struct
{
u32 itow; // ms GPS Millisecond Time of Week
s32 VEL_N; // cm/s NED north velocity
s32 VEL_E; // cm/s NED east velocity
s32 VEL_D; // cm/s NED down velocity
u32 Speed; // cm/s Speed (3-D)
u32 GSpeed; // cm/s Ground Speed (2-D)
s32 Heading; // 1e-05 deg Heading 2-D
u32 SAcc; // cm/s Speed Accuracy Estimate
u32 CAcc; // deg Course / Heading Accuracy Estimate
Status_t Status; // invalid/newdata/processed
} __attribute__((packed)) ubx_nav_velned_t;
 
typedef struct
{
u32 itow; // ms GPS Millisecond Time of Week
s32 LON; // 1e-07 deg Longitude
s32 LAT; // 1e-07 deg Latitude
s32 HEIGHT; // mm Height above Ellipsoid
s32 HMSL; // mm Height above mean sea level
u32 Hacc; // mm Horizontal Accuracy Estimate
u32 Vacc; // mm Vertical Accuracy Estimate
Status_t Status; // invalid/newdata/processed
} __attribute__((packed)) ubx_nav_posllh_t;
 
 
 
//------------------------------------------------------------------------------------
// global variables
 
// local buffers for the incomming ubx messages
volatile ubx_nav_sol_t UbxSol = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, INVALID};
volatile ubx_nav_posllh_t UbxPosLlh = {0,0,0,0,0,0,0, INVALID};
volatile ubx_nav_velned_t UbxVelNed = {0,0,0,0,0,0,0,0,0, INVALID};
 
// shared buffer
volatile gps_data_t GPSData = {0,0,0,0,0,0,0,0,0,0, INVALID};
DateTime_t GPSDateTime = {0,0,0,0,0,0,0, INVALID};
 
 
 
//------------------------------------------------------------------------------------
// functions
 
u8 IsLeapYear(u16 year)
{
if((year%400 == 0) || ( (year%4 == 0) && (year%100 != 0) ) ) return 1;
else return 0;
}
/********************************************************/
/* Calculates the UTC Time from the GPS week and tow */
/********************************************************/
void SetGPSTime(DateTime_t * pTimeStruct)
{
u32 Days, Seconds, Week;
u16 YearPart;
u32 * MonthDayTab = 0;
u8 i;
 
 
 
// if GPS data show valid time data
if((UbxSol.Status != INVALID) && (UbxSol.Flags & FLAG_WKNSET) && (UbxSol.Flags & FLAG_TOWSET) )
{
Seconds = UbxSol.itow / 1000L;
Week = (u32)UbxSol.week;
// correct leap seconds since 1980
if(Seconds < LEAP_SECONDS_FROM_1980)
{
Week--;
Seconds = SECONDS_PER_WEEK - LEAP_SECONDS_FROM_1980 + Seconds;
}
else Seconds -= LEAP_SECONDS_FROM_1980;
 
Days = DAYS_FROM_JAN01YEAR0001_TO_JAN6_1980;
Days += (Week * DAYS_PER_WEEK);
Days += Seconds / SECONDS_PER_DAY; // seperate days from GPS seconds of week
 
pTimeStruct->Year = 1;
YearPart = (u16)(Days / DAYS_PER_400YEARS);
pTimeStruct->Year += YearPart * 400;
Days = Days % DAYS_PER_400YEARS;
YearPart = (u16)(Days / DAYS_PER_100YEARS);
pTimeStruct->Year += YearPart * 100;
Days = Days % DAYS_PER_100YEARS;
YearPart = (u16)(Days / DAYS_PER_4YEARS);
pTimeStruct->Year += YearPart * 4;
Days = Days % DAYS_PER_4YEARS;
if(Days < (3* DAYS_PER_YEAR)) YearPart = (u16)(Days / DAYS_PER_YEAR);
else YearPart = 3;
pTimeStruct->Year += YearPart;
// calculate remaining days of year
Days -= (u32)(YearPart * DAYS_PER_YEAR);
Days += 1;
// check if current year is a leap year
if(IsLeapYear(pTimeStruct->Year)) MonthDayTab = (u32*)Leap;
else MonthDayTab = (u32*)Normal;
// seperate month and day from days of year
for ( i = 0; i < 12; i++ )
{
if ( (MonthDayTab[i]< Days) && (Days <= MonthDayTab[i+1]) )
{
pTimeStruct->Month = i+1;
pTimeStruct->Day = Days - MonthDayTab[i];
i = 12;
}
}
Seconds = Seconds % SECONDS_PER_DAY; // remaining seconds of current day
pTimeStruct->Hour = (u8)(Seconds / SECONDS_PER_HOUR);
Seconds = Seconds % SECONDS_PER_HOUR; // remaining seconds of current hour
pTimeStruct->Min = (u8)(Seconds / SECONDS_PER_MINUTE);
Seconds = Seconds % SECONDS_PER_MINUTE; // remaining seconds of current minute
pTimeStruct->Sec = (u8)(Seconds);
pTimeStruct->mSec = (u16)(UbxSol.itow % 1000L);
pTimeStruct->Valid = 1;
}
else
{
pTimeStruct->Valid = 0;
}
}
 
 
 
/********************************************************/
/* Initialize UBX Parser */
/********************************************************/
void UBX_Init(void)
{
// mark msg buffers invalid
UbxSol.Status = INVALID;
UbxPosLlh.Status = INVALID;
UbxVelNed.Status = INVALID;
GPSData.Status = INVALID;
}
 
/********************************************************/
/* Upate GPS data stcructure */
/********************************************************/
void Update_GPSData (void)
{
if ((UbxSol.Status == NEWDATA) && (UbxPosLlh.Status == NEWDATA) && (UbxVelNed.Status == NEWDATA))
{
LED_RED_TOGGLE;
// update GPS data only if the status is INVALID or PROCESSED
if(GPSData.Status != NEWDATA) // if last data were processed
{ // wait for new data at all neccesary ubx messages
GPSData.Status = INVALID;
// NAV SOL
GPSData.Flags = UbxSol.Flags;
GPSData.NumOfSats = UbxSol.numSV;
GPSData.SatFix = UbxSol.GPSfix;
GPSData.Position_Accuracy = UbxSol.PAcc;
GPSData.Speed_Accuracy = UbxSol.SAcc;
SetGPSTime(&SystemTime); // update system time
// NAV POSLLH
GPSData.Longitude = UbxPosLlh.LON;
GPSData.Latitude = UbxPosLlh.LAT;
GPSData.Altitude = UbxPosLlh.HMSL;
// NAV VELNED
GPSData.Speed_East = UbxVelNed.VEL_E;
GPSData.Speed_North = UbxVelNed.VEL_N;
GPSData.Speed_Top = -UbxVelNed.VEL_D;
GPSData.Speed_Ground = UbxVelNed.GSpeed;
GPSData.Status = NEWDATA; // new data available
}
// set state to collect new data
UbxSol.Status = PROCESSED; // ready for new data
UbxPosLlh.Status = PROCESSED; // ready for new data
UbxVelNed.Status = PROCESSED; // ready for new data
}
}
 
 
/********************************************************/
/* UBX Parser */
/********************************************************/
void UBX_Parser(u8 c)
{
static ubxState_t ubxState = UBXSTATE_IDLE;
static u16 msglen;
static u8 cka, ckb;
static u8 *ubxP, *ubxEp, *ubxSp; // pointers to data currently transfered
 
//state machine
switch (ubxState) // ubx message parser
{
case UBXSTATE_IDLE: // check 1st sync byte
if (c == UBX_SYNC1_CHAR) ubxState = UBXSTATE_SYNC1;
else ubxState = UBXSTATE_IDLE; // out of synchronization
break;
 
case UBXSTATE_SYNC1: // check 2nd sync byte
if (c == UBX_SYNC2_CHAR) ubxState = UBXSTATE_SYNC2;
else ubxState = UBXSTATE_IDLE; // out of synchronization
break;
 
case UBXSTATE_SYNC2: // check msg class to be NAV
if (c == UBX_CLASS_NAV) ubxState = UBXSTATE_CLASS;
else ubxState = UBXSTATE_IDLE; // unsupported message class
break;
 
case UBXSTATE_CLASS: // check message identifier
switch(c)
{
case UBX_ID_POSLLH: // geodetic position
ubxP = (u8 *)&UbxPosLlh; // data start pointer
ubxEp = (u8 *)(&UbxPosLlh + 1); // data end pointer
ubxSp = (u8 *)&UbxPosLlh.Status; // status pointer
break;
 
case UBX_ID_SOL: // navigation solution
ubxP = (u8 *)&UbxSol; // data start pointer
ubxEp = (u8 *)(&UbxSol + 1); // data end pointer
ubxSp = (u8 *)&UbxSol.Status; // status pointer
break;
 
case UBX_ID_VELNED: // velocity vector in tangent plane
ubxP = (u8 *)&UbxVelNed; // data start pointer
ubxEp = (u8 *)(&UbxVelNed + 1); // data end pointer
ubxSp = (u8 *)&UbxVelNed.Status; // status pointer
break;
 
default: // unsupported identifier
ubxState = UBXSTATE_IDLE;
break;
}
if (ubxState != UBXSTATE_IDLE)
{
ubxState = UBXSTATE_LEN1;
cka = UBX_CLASS_NAV + c;
ckb = UBX_CLASS_NAV + cka;
}
break;
 
case UBXSTATE_LEN1: // 1st message length byte
msglen = (u16)c; // lowbyte first
cka += c;
ckb += cka;
ubxState = UBXSTATE_LEN2;
break;
 
case UBXSTATE_LEN2: // 2nd message length byte
msglen += ((u16)c)<<8; // high byte last
cka += c;
ckb += cka;
// if the old data are not processed so far then break parsing now
// to avoid writing new data in ISR during reading by another function
if ( *ubxSp == NEWDATA )
{
ubxState = UBXSTATE_IDLE;
Update_GPSData(); //update GPS info respectively
}
else // data invalid or allready processd
{
*ubxSp = INVALID; // mark invalid during buffer filling
ubxState = UBXSTATE_DATA;
}
break;
 
case UBXSTATE_DATA: // collecting data
if (ubxP < ubxEp) *ubxP++ = c; // copy curent data byte if any space is left
cka += c;
ckb += cka;
if (--msglen == 0) ubxState = UBXSTATE_CKA; // switch to next state if all data was read
break;
 
case UBXSTATE_CKA:
if (c == cka) ubxState = UBXSTATE_CKB;
else
{
*ubxSp = INVALID;
ubxState = UBXSTATE_IDLE;
}
break;
 
case UBXSTATE_CKB:
if (c == ckb)
{
*ubxSp = NEWDATA; // new data are valid
Update_GPSData(); //update GPS info respectively
}
else
{ // if checksum not match then set data invalid
*ubxSp = INVALID;
}
ubxState = UBXSTATE_IDLE; // ready to parse new data
break;
 
default: // unknown ubx state
ubxState = UBXSTATE_IDLE;
break;
 
}
}
/branches/V0.1 killagreg/ubx.h
0,0 → 1,48
#ifndef __UBX_H
#define __UBX_H
 
// Satfix types for GPSData.SatFix
#define SATFIX_NONE 0x00
#define SATFIX_DEADRECKOING 0x01
#define SATFIX_2D 0x02
#define SATFIX_3D 0x03
#define SATFIX_GPS_DEADRECKOING 0x04
#define SATFIX_TIMEONLY 0x05
// Flags for interpretation of the GPSData.Flags
#define FLAG_GPSFIXOK 0x01 // (i.e. within DOP & ACC Masks)
#define FLAG_DIFFSOLN 0x02 // (is DGPS used)
#define FLAG_WKNSET 0x04 // (is Week Number valid)
#define FLAG_TOWSET 0x08 // (is Time of Week valid)
 
typedef enum
{
INVALID,
NEWDATA,
PROCESSED
} Status_t;
 
typedef struct
{
u8 Flags; // Status Flags
u8 NumOfSats; // number of satelites
u8 SatFix; // type of satfix
s32 Longitude; // in 1e-07 deg
s32 Latitude; // in 1e-07 deg
s32 Altitude; // in mm
u32 Position_Accuracy; // in cm 3d position accuracy
s32 Speed_North; // in cm/s
s32 Speed_East; // in cm/s
s32 Speed_Top; // in cm/s
u32 Speed_Ground; // 2D ground speed in cm/s
u32 Speed_Accuracy; // in cm/s 3d velocity accuracy
Status_t Status; // status of data
} __attribute__((packed)) gps_data_t;
 
// The data are valid if the GPSData.Status is NEWDATA or PROCESSED.
// To achieve new data after reading the GPSData.Status should be set to PROCESSED.
extern volatile gps_data_t GPSData;
 
void UBX_Init(void);
void UBX_Parser(u8 c);
 
#endif // __UBX_H
/branches/V0.1 killagreg/usb.c
55,18 → 55,21
// + POSSIBILITY OF SUCH DAMAGE.
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#include "91x_lib.h"
#include "uart1.h"
#include "usb.h"
#include "uart.h"
 
//-----------------------------------------------------------------
void USB_ConfigInit(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
SerialPutString("USB init...");
//USB clock = MCLK= 48MHz
SerialPutString("\r\n USB init...");
#ifdef MCLK96MHZ
//USB clock = MCLK/2 = 48MHz
SCU_USBCLKConfig(SCU_USBCLK_MCLK2);
#else
//USB clock = MCLK = 48MHz
SCU_USBCLKConfig(SCU_USBCLK_MCLK);
#endif
//Enable USB clock
SCU_AHBPeriphClockConfig(__USB,ENABLE);
SCU_AHBPeriphReset(__USB,DISABLE);
77,6 → 80,7
SCU_APBPeriphReset(__GPIO0,DISABLE);
 
// GPIO_DeInit(P0.1);
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Direction = GPIO_PinOutput;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull ;
92,7 → 96,7
USB_Init();
SerialPutString("ok\n\r");
SerialPutString("ok");
}
 
//-----------------------------------------------------------------
/branches/V0.1 killagreg/usb_endp.c
16,9 → 16,11
*******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include <stdio.h>
#include "91x_lib.h"
#include "uart1.h"
#include "usb_lib.h"
#include "usb_desc.h"
#include "uart.h"
 
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/