Subversion Repositories Projects

Compare Revisions

Ignore whitespace Rev 230 → Rev 231

/FollowMe/Hex-Files/BootLoader_MEGA644p_20MHZ_V0_1.hex
0,0 → 1,64
:10F8000011241FBECFEFD0E1DEBFCDBF11E0A0E0DD
:10F81000B1E0E0EEFBEF02C005900D92A030B10721
:10F82000D9F712E0A0E0B1E001C01D92A230B1070B
:10F83000E1F70C943B7C0C941D7C0895982F8091EB
:10F84000C00085FFFCCF9093C60008958091C00052
:10F850008823E4F78091C600992708958DE40E94DB
:10F860001E7C8BE40E941E7C82E40E941E7C8CE441
:10F870000E941E7C0895CFEFD0E1DEBFCDBFE0E057
:10F88000F0E014915F01772474BE98E10FB6F8940C
:10F8900090936000109260000FBE7092C5008AE2E3
:10F8A0008093C4008091C00082608093C0009093D8
:10F8B000C10086E08093C200EF01072D8091C00057
:10F8C00087FF0DC0013031F48091C6008A3AB1F152
:10F8D00000E005C08091C6008B3109F401E0CE0143
:10F8E00021968436910528F11F3F41F0112331F014
:10F8F000E0910001F091010109951BC01092C50033
:10F900008AE28093C4008AE00E941E7C8DE00E94FF
:10F910001E7C86E50E941E7C80E30E941E7C8EE297
:10F920000E941E7C81E30E941E7C8AE30E941E7C52
:10F9300005C080E593EC0197F1F7C0CF0E942E7CC3
:10F940000E94267C813611F489E547C1813471F427
:10F950000E94267CA82EBB24BA2CAA240E94267CB6
:10F960009927A82AB92AB694A79406C1823629F401
:10F9700089E50E941E7C81E00BC1823409F083C0BE
:10F980000E94267C9927D82FCC270E94267C992775
:10F99000C82BD92B0E94267C082F12E0812E11E063
:10F9A000912EEE24FF2464010894811C911CEC1616
:10F9B000FD0618F40E94267C01C08FEFD6018C93BF
:10F9C0000894E11CF11CBFEFEB16F10461F358F34E
:10F9D000E4E77E1609F0DEC0063409F03DC0FFEF13
:10F9E000AF16F7EFBF0608F033C0DE01A5016627AA
:10F9F0007727440F551F661F771F6A017B01C2E0FE
:10FA0000D1E001E08991992729913327322F2227CC
:10FA1000822B932B0C01FA0100935700E8951124D7
:10FA20004E5F5F4F6F4F7F4F129761F785E0F60192
:10FA300080935700E89507B600FCFDCF81E18093E5
:10FA40005700E89576956795579547955A0194C064
:10FA500080E00E941E7C90C0053409F08DC0F50145
:10FA60009E01A2E0B1E0E1BD8F2F992782BD8D916B
:10FA700080BD3196FA9AF99AF999FECF215030401B
:10FA800091F75F0179C0873609F047C00E94267C54
:10FA90009927D82ECC240E94267C9927C82AD92AB7
:10FAA0000E94267C863411F5E6016501EE24FF24D0
:10FAB000CC0CDD1CEE1CFF1CF60105911491802F6F
:10FAC0000E941E7C812F99270E941E7C82E090E07C
:10FAD000A0E0B0E0C80ED91EEA1EFB1E229761F717
:10FAE000F694E794D794C79456012ACF853409F049
:10FAF00027CF7501E1BC8F2D992782BDF89A089414
:10FB0000E11CF11C80B50E941E7C0894C108D1083C
:10FB1000C114D10479F7570113CF853601F594E765
:10FB2000791651F580E090E0A0E0B0E023E0FC0120
:10FB300020935700E89507B600FCFDCF80509F4FFB
:10FB4000AF4FBF4F8F3FE7EF9E07E0E0AE07E0E02B
:10FB5000BE0768F381E180935700E8950DC08534B6
:10FB600069F488E190E02CE00FB6F894A8958093B2
:10FB700060000FBE209360008DE02FC08035E1F360
:10FB80008C34D1F3803711F483E527C0843721F416
:10FB90000E941E7C80E021C0843521F40E94267CD6
:10FBA000782EEACF8B3109F4C9CE8A3A09F4C6CE51
:10FBB000863529F480E30E941E7C81E30EC08337E2
:10FBC00041F489E00E941E7C86E90E941E7C8EE141
:10FBD00004C08B3109F4B4CE8FE30E941E7CB0CEFA
:040000030000F80001
:00000001FF
/FollowMe/Hex-Files/Conrad LEA-4H Config-4Hz.txt
0,0 → 1,58
MON-VER - 0A 04 46 00 35 2E 30 30 20 20 20 20 4A 75 6C 20 31 37 20 32 30 30 36 20 31 35 3A 30 38 3A 31 30 00 01 30 30 30 34 30 30 30 31 00 00 4D 34 48 31 2E 31 43 20 4A 75 6C 20 31 37 20 32 30 30 36 20 31 36 3A 34 32 3A 33 30 00 00
CFG-ANT - 06 13 04 00 0B 00 0F 38
CFG-DAT - 06 06 02 00 00 00
CFG-FXN - 06 0E 24 00 12 00 00 00 C0 D4 01 00 C0 D4 01 00 C0 27 09 00 C0 27 09 00 A0 8C 00 00 40 77 1B 00 00 00 00 00 00 00 00 00
CFG-INF - 06 02 08 00 00 00 00 00 00 87 00 00
CFG-INF - 06 02 08 00 01 00 00 00 00 00 00 87
CFG-INF - 06 02 08 00 03 00 00 00 00 00 00 00
CFG-MSG - 06 01 06 00 01 01 00 00 00 00
CFG-MSG - 06 01 06 00 01 02 00 01 00 00
CFG-MSG - 06 01 06 00 01 03 00 00 00 00
CFG-MSG - 06 01 06 00 01 04 00 00 00 00
CFG-MSG - 06 01 06 00 01 06 00 01 00 00
CFG-MSG - 06 01 06 00 01 08 00 00 00 00
CFG-MSG - 06 01 06 00 01 11 00 00 00 00
CFG-MSG - 06 01 06 00 01 12 00 01 00 00
CFG-MSG - 06 01 06 00 01 20 00 00 00 00
CFG-MSG - 06 01 06 00 01 21 00 00 00 00
CFG-MSG - 06 01 06 00 01 22 00 00 00 00
CFG-MSG - 06 01 06 00 01 30 00 00 00 00
CFG-MSG - 06 01 06 00 01 31 00 00 00 00
CFG-MSG - 06 01 06 00 01 32 00 00 00 00
CFG-MSG - 06 01 06 00 02 10 00 00 00 00
CFG-MSG - 06 01 06 00 02 11 00 00 00 00
CFG-MSG - 06 01 06 00 02 20 00 00 00 00
CFG-MSG - 06 01 06 00 0A 01 00 00 00 00
CFG-MSG - 06 01 06 00 0A 02 00 00 00 00
CFG-MSG - 06 01 06 00 0A 03 00 00 00 00
CFG-MSG - 06 01 06 00 0A 06 00 00 00 00
CFG-MSG - 06 01 06 00 0A 07 00 00 00 00
CFG-MSG - 06 01 06 00 0A 08 00 00 00 00
CFG-MSG - 06 01 06 00 0A 09 00 00 00 00
CFG-MSG - 06 01 06 00 0B 00 00 00 00 00
CFG-MSG - 06 01 06 00 0B 30 00 00 00 00
CFG-MSG - 06 01 06 00 0B 31 00 00 00 00
CFG-MSG - 06 01 06 00 0D 01 00 00 00 00
CFG-MSG - 06 01 06 00 0D 03 00 00 00 00
CFG-MSG - 06 01 06 00 F0 00 00 00 00 01
CFG-MSG - 06 01 06 00 F0 01 00 00 00 01
CFG-MSG - 06 01 06 00 F0 02 00 00 00 01
CFG-MSG - 06 01 06 00 F0 03 00 00 00 01
CFG-MSG - 06 01 06 00 F0 04 00 00 00 01
CFG-MSG - 06 01 06 00 F0 05 00 00 00 01
CFG-MSG - 06 01 06 00 F0 06 00 00 00 00
CFG-MSG - 06 01 06 00 F0 07 00 00 00 00
CFG-MSG - 06 01 06 00 F0 08 00 00 00 01
CFG-MSG - 06 01 06 00 F1 00 00 00 00 00
CFG-MSG - 06 01 06 00 F1 01 00 00 00 00
CFG-MSG - 06 01 06 00 F1 03 00 00 00 00
CFG-MSG - 06 01 06 00 F1 04 00 00 00 00
CFG-NAV2 - 06 1A 28 00 03 00 00 00 03 03 10 02 50 C3 00 00 0F 0A 05 3C 00 01 00 00 FA 00 FA 00 64 00 2C 01 00 00 00 00 00 00 00 00 00 00 00 00
CFG-NMEA - 06 17 04 00 00 23 00 02
CFG-PRT - 06 00 14 00 01 00 00 00 D0 08 08 00 00 E1 00 00 01 00 01 00 00 00 00 00
CFG-PRT - 06 00 14 00 02 00 00 00 D0 08 08 00 00 E1 00 00 01 00 01 00 00 00 00 00
CFG-PRT - 06 00 14 00 03 00 00 00 00 00 00 00 00 00 00 00 03 00 03 00 00 00 00 00
CFG-RATE - 06 08 06 00 FA 00 01 00 00 00
CFG-RXM - 06 11 02 00 03 00
CFG-SBAS - 06 16 08 00 00 00 01 00 00 00 00 00
CFG-TP - 06 07 14 00 40 42 0F 00 A0 86 01 00 01 01 00 00 32 00 34 03 00 00 00 00
/FollowMe/Hex-Files/Conrad LEA-4H Config-5Hz.txt
0,0 → 1,58
MON-VER - 0A 04 46 00 35 2E 30 30 20 20 20 20 4A 75 6C 20 31 37 20 32 30 30 36 20 31 35 3A 30 38 3A 31 30 00 01 30 30 30 34 30 30 30 31 00 00 4D 34 48 31 2E 31 43 20 4A 75 6C 20 31 37 20 32 30 30 36 20 31 36 3A 34 32 3A 33 30 00 00
CFG-ANT - 06 13 04 00 0B 00 0F 38
CFG-DAT - 06 06 02 00 00 00
CFG-FXN - 06 0E 24 00 12 00 00 00 C0 D4 01 00 C0 D4 01 00 C0 27 09 00 C0 27 09 00 A0 8C 00 00 40 77 1B 00 00 00 00 00 00 00 00 00
CFG-INF - 06 02 08 00 00 00 00 00 00 87 00 00
CFG-INF - 06 02 08 00 01 00 00 00 00 00 00 87
CFG-INF - 06 02 08 00 03 00 00 00 00 00 00 00
CFG-MSG - 06 01 06 00 01 01 00 00 00 00
CFG-MSG - 06 01 06 00 01 02 00 01 00 00
CFG-MSG - 06 01 06 00 01 03 00 00 00 00
CFG-MSG - 06 01 06 00 01 04 00 00 00 00
CFG-MSG - 06 01 06 00 01 06 00 01 00 00
CFG-MSG - 06 01 06 00 01 08 00 00 00 00
CFG-MSG - 06 01 06 00 01 11 00 00 00 00
CFG-MSG - 06 01 06 00 01 12 00 01 00 00
CFG-MSG - 06 01 06 00 01 20 00 00 00 00
CFG-MSG - 06 01 06 00 01 21 00 00 00 00
CFG-MSG - 06 01 06 00 01 22 00 00 00 00
CFG-MSG - 06 01 06 00 01 30 00 00 00 00
CFG-MSG - 06 01 06 00 01 31 00 00 00 00
CFG-MSG - 06 01 06 00 01 32 00 00 00 00
CFG-MSG - 06 01 06 00 02 10 00 00 00 00
CFG-MSG - 06 01 06 00 02 11 00 00 00 00
CFG-MSG - 06 01 06 00 02 20 00 00 00 00
CFG-MSG - 06 01 06 00 0A 01 00 00 00 00
CFG-MSG - 06 01 06 00 0A 02 00 00 00 00
CFG-MSG - 06 01 06 00 0A 03 00 00 00 00
CFG-MSG - 06 01 06 00 0A 06 00 00 00 00
CFG-MSG - 06 01 06 00 0A 07 00 00 00 00
CFG-MSG - 06 01 06 00 0A 08 00 00 00 00
CFG-MSG - 06 01 06 00 0A 09 00 00 00 00
CFG-MSG - 06 01 06 00 0B 00 00 00 00 00
CFG-MSG - 06 01 06 00 0B 30 00 00 00 00
CFG-MSG - 06 01 06 00 0B 31 00 00 00 00
CFG-MSG - 06 01 06 00 0D 01 00 00 00 00
CFG-MSG - 06 01 06 00 0D 03 00 00 00 00
CFG-MSG - 06 01 06 00 F0 00 00 00 00 01
CFG-MSG - 06 01 06 00 F0 01 00 00 00 01
CFG-MSG - 06 01 06 00 F0 02 00 00 00 01
CFG-MSG - 06 01 06 00 F0 03 00 00 00 01
CFG-MSG - 06 01 06 00 F0 04 00 00 00 01
CFG-MSG - 06 01 06 00 F0 05 00 00 00 01
CFG-MSG - 06 01 06 00 F0 06 00 00 00 00
CFG-MSG - 06 01 06 00 F0 07 00 00 00 00
CFG-MSG - 06 01 06 00 F0 08 00 00 00 01
CFG-MSG - 06 01 06 00 F1 00 00 00 00 00
CFG-MSG - 06 01 06 00 F1 01 00 00 00 00
CFG-MSG - 06 01 06 00 F1 03 00 00 00 00
CFG-MSG - 06 01 06 00 F1 04 00 00 00 00
CFG-NAV2 - 06 1A 28 00 03 00 00 00 03 03 10 02 50 C3 00 00 0F 0A 05 3C 00 01 00 00 FA 00 FA 00 64 00 2C 01 00 00 00 00 00 00 00 00 00 00 00 00
CFG-NMEA - 06 17 04 00 00 23 00 02
CFG-PRT - 06 00 14 00 01 00 00 00 D0 08 08 00 00 E1 00 00 01 00 01 00 00 00 00 00
CFG-PRT - 06 00 14 00 02 00 00 00 D0 08 08 00 00 E1 00 00 01 00 01 00 00 00 00 00
CFG-PRT - 06 00 14 00 03 00 00 00 00 00 00 00 00 00 00 00 03 00 03 00 00 00 00 00
CFG-RATE - 06 08 06 00 64 00 02 00 00 00
CFG-RXM - 06 11 02 00 03 00
CFG-SBAS - 06 16 08 00 00 00 01 00 00 00 00 00
CFG-TP - 06 07 14 00 40 42 0F 00 A0 86 01 00 01 01 00 00 32 00 34 03 00 00 00 00
/FollowMe/fat16.c
0,0 → 1,1482
#include <stdio.h>
#include <avr/io.h>
#include "fat16.h"
#include "sdc.h"
#include "printf_P.h"
 
 
//________________________________________________________________________________________________________________________________________
// Module name: fat16.c
// Compiler used: avr-gcc 3.4.5
// Last Modifikation: 28.03.2008
// Version: 1.25
// Authors: Stephan Busker
// Description: Source files for FAT16 implementation with read and write-access using AVR-Mikrocontrollers
// Copyright (C) 2007 Stephan Busker
//........................................................................................................................................
// Functions: extern u8 FAT16_Init(void);
// u8 fopen_(s8 *fname,s8 mode, File *file);
// void fclose_(File *file);
// u32 fread_(void *buffer, u32 size, u32 count, File *file);
// u32 fwrite_(void *buffer, u32 size, u32 count, File *file);
// s16 fseek_(File *file, s32 offset, s16 origin);
// s8 fgets_(s8 *string, s16 count, File *file);
// u8 fputchar_(File *file,s8 c);
// u8 fputs_(File *file,s8 *string);
// s8 * fgets(s8 *, s16, File);
// u8 fexist_(u8*, File *file);
// u8 mkdir__(s8 *name);
// u8 chdir__(s8 *name);
// u8 findfirst_(s8 *fname, Find *item, u8 attribute);
// u8 findnext_(Find *item);
// u8 fdelete_(s8 *fname)
// u8 rmdir_(s8 *dname)
//........................................................................................................................................
// ext. functions: extern u8 SDC_GetSector (u32,u8 *);
// extern u8 SDC_PutSector (u32,u8 *);
//........................................................................................................................................
//
// URL: www.Mikro-Control.de
// mailto: stephan.busker@mikro-control.de
//________________________________________________________________________________________________________________________________________
 
u8 text[80];
 
 
//________________________________________________________________________________________________________________________________________
//
// Global variables needed for read- or write-acces to the FAT16- filesystem.
//
//________________________________________________________________________________________________________________________________________
 
u8 SectorsPerCluster = 0; // how many sectors does a cluster contain?
u8 FatCopies = 0; // Numbers of copies of the FAT
u16 PossibleRootEntries = 0; // Possible number of entries in the root directory.
u16 SectorsPerFat = 0; // how many sectors does a fat16 contain?
u32 ReservedSectors = 0; // Sectors reserved by the filesystem.
u32 FirstPartitionSector = 0; // Distance in sectors between the first partition and the master bootrecord.
u32 FileAllocationTable = 0; // pointer to the first FAT
u32 RootDirectory = 0; // Pointer to the rootdirectory of the first partition.
u32 FirstDataCluster = 0; // Pointer to the first cluster containing data (cluster0).
u32 CWD = 0; // Pointer startcluster to the current working directory
 
 
struct DirEntry *DirectoryEntry; // Pointer to an entry of the directory.
struct FatEntry *Fat; // Pointer to an entry of the fat (next clusterposition).
 
File FilePointer[__MAX_FILES_USED]; // Allocate Memmoryspace for each filepointer used.
 
 
//________________________________________________________________________________________________________________________________________
// Funtion: InitFat16(void);
//
// Description: This function reads the Masterbootrecord and finds the position of the Volumebootrecord, the FAT and the Rootdirectory
// and stores the information in global variables.
//
// Returnvalue: The function returns "0" if the filesystem could not be initialized because no partition was found on the disc.
//________________________________________________________________________________________________________________________________________
 
u8 FAT16_Init(void)
{
u8 retvalue = 0;
u8 cnt = 0;
struct VBR_Entry *VBR; // Pointer to the VolumeBootRecord.
struct MBR_Entry *MBR; // Pointer to the masterbootrecord.
File *file;
 
for(cnt=0;cnt<__MAX_FILES_USED;cnt++)
{
FilePointer[cnt].state = _UNUSED; // declare the filepointers as unused.
}
 
file = &FilePointer[0];
 
while((SDC_Init() != 0) && (cnt++<200)); // initialise the sdcard.
if(cnt <200) //sdcard initialised succesfully
{
SDC_GetSector((u32)_MBR_SECTOR,file->buffer); // Read the MasterBootRecord from mmc.
MBR = (struct MBR_Entry *) file->buffer;
FirstPartitionSector = MBR->PartitionEntry1.NoSectorsBeforePartition;
if((MBR->PartitionEntry1.Type == _FAT16_32_MB_BIOS_Extension) ||
(MBR->PartitionEntry1.Type == _FAT16_ST_32_MB) ||
(MBR->PartitionEntry1.Type == _FAT16_LT_32_MB))
{
SDC_GetSector(FirstPartitionSector,file->buffer); // Read the volume bootrecord from mmc.
 
VBR = (struct VBR_Entry *) file->buffer; // Enter the VBR using the structure VBR_Entry.
SectorsPerCluster = VBR->SectorsPerCluster; // Number of sectors per cluster. Depends on the memorysize of the sd-card.
FatCopies = VBR->NoFATCopies; // Number of fatcopies.
PossibleRootEntries = VBR->MaxRootEntries; // How many Entries are possible in the rootdirectory (FAT16 allows max. 512 entries).
SectorsPerFat = VBR->SectorsPerFAT; // The number of sectors per FAT.
ReservedSectors = VBR->ReservedSectors; // calculate the sectorpositon of the FAT, the Rootdirectory and the first Datacluster.
 
FileAllocationTable = (u32)(FirstPartitionSector + (u32)ReservedSectors); // Calculate the position of the FileAllocationTable.
RootDirectory = (u32)((u32)FileAllocationTable + (u32)((u32)SectorsPerFat*(u32)FatCopies)); // Calculate the position of the Rootdirectory.
FirstDataCluster = (u32)((u32)RootDirectory + ((u32)(PossibleRootEntries>>4))); // Calculate the position of the first datacluster.
CWD = RootDirectory; // The actual directory is the rootdirectory.
retvalue = 1;
}
}
return(retvalue);
}
 
//________________________________________________________________________________________________________________________________________
// Funtion: File * fopen_(u8*, u8 *);
//
// Description: This function looks for the file in the directory specified by the variable "CWD" of the drive. If the file is found the number of the
// corrosponding datacluster is returned to main. Only modes 'r' (reading) and 'a' append are implemented yet.
//
// Return: 0 = faild to open speicified file
// 1 = file opened
//________________________________________________________________________________________________________________________________________
 
File * fopen_(s8 *fname, s8 mode)
{
File *file;
 
file = ReserveFilePointer(); // reserve a filepointer.
 
if(file != NULL) // A free filepointer was found.
{
file->mode = mode; // mode of fileoperation (read,write)
 
if(SeekFileInDirectory(fname, file)) // if file was found
{
if(mode == 'a') // open existing file for writing (append data at the end of the file)
{
fseek_(file, 0, SEEK_END); // fseek points to the end of the file
}
else if(mode == 'r')
{
return(file);
}
else
{
fclose_(file);
file = NULL;
}
 
}
else
{
if((mode == 'a') || (mode == 'w')) // specified file doesn't exist so create new file for writing data.
{
if(CreateFileInDirectory(fname,file)) // Could an entry for the new file in the rootdirectory be created?
{
return(file);
}
else
{
fclose_(file);
file = NULL;
}
}
}
}
return(file);
}
 
 
 
//________________________________________________________________________________________________________________________________________
// Funtion: fflush_(File *file);
//
// Description: This function writes the data already in the buffer but not yet written to the file.
//
//________________________________________________________________________________________________________________________________________
 
s16 fflush_(File *file)
{
u16 time=0;
u16 date=0;
 
 
if(file && ((file->mode =='a') || (file->mode =='w')))
{
if(file->byte_index > 0) // has data been added to the file?
{
SDC_PutSector((u32)(file->cluster_pointer + file->sector_index),file->buffer);// save the data still in the buffer
}
SDC_GetSector((u32)file->directory_sector,file->buffer); // read the directoryentry for this file.
DirectoryEntry = (struct DirEntry *)file->buffer;
DirectoryEntry[file->directory_index].size = (u32) file->filesize;
DirectoryEntry[file->directory_index].time = (u16) time;
DirectoryEntry[file->directory_index].date = (u16) date;
SDC_PutSector((u32)file->directory_sector,file->buffer);
}
return(0);
}
 
//________________________________________________________________________________________________________________________________________
// Funtion: fclose_(File *file);
//
// Description: This function closes the open file by writing the remaining data from the buffer to the device and entering the filesize
// in the directory entry.
//________________________________________________________________________________________________________________________________________
 
void fclose_(File *file)
{
if(file != NULL)
{
fflush_(file); // save buffered data to the disk
}
FreeFilePointer(file); // and free the filepointer.
}
 
//________________________________________________________________________________________________________________________________________
// Funtion: u32 fread_(void *buffer, s32 size, s32 count, File *file);
//
// Description: This function reads count objects of the specified size from the actual position of the file to the specified buffer.
//
// Returnvalue: The function returns the number of objects (not bytes) read from the file.
//
//________________________________________________________________________________________________________________________________________
 
u32 fread_(void *buffer, u32 size, u32 count, File *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.
u8 *buff_pnt = 0; // a pointer to the actual bufferposition.
u8 success = 1; // no error occured during read operation to the file.
 
buff_pnt = (u8 *) buffer; // cast the void pointer to an u8 *
 
while((object_cnt < count) && success)
{
object_size = size;
while((size > 0) && success)
{
*buff_pnt = (u8) fgetchar_(file); // read a byte from the buffer to the opened file.
buff_pnt++;
size--;
}
if(success) object_cnt++;
}
 
return(object_cnt); // return the number of objects succesfully read from the file
}
 
//________________________________________________________________________________________________________________________________________
// Funtion: u32 fwrite_(void *buffer, s32 size, s32 count, File *file);
//
// Description: This function writes count objects of the specified size from the buffer to the actual positon within the file.
//
// Returnvalue: The function returns the number of objects (not bytes) written to the file.
//
//________________________________________________________________________________________________________________________________________
 
u32 fwrite_(void *buffer, u32 size, u32 count, File *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.
u8 *buff_pnt = 0; // a pointer to the actual bufferposition.
u8 success = 1; // no error occured during write operation to the file.
 
buff_pnt = (u8 *) buffer; // cast the void pointer to an u8 *
 
while((object_cnt < count) && success)
{
object_size = size;
while((size > 0) && success)
{
success = fputchar_(file, *buff_pnt); // write a byte from the buffer to the opened file.
buff_pnt++;
size--;
}
if(success) object_cnt++;
}
 
return(object_cnt); // return the number of objects succesfully written to the file
} // (!!!!! objects and not bytes !!!!)
 
//________________________________________________________________________________________________________________________________________
// Funtion: s16 fseek_(File *, s32, s16)
//
// Description: This function sets the pointer of the stream relative to the position
// specified by origin (SEEK_SET, SEEK_CUR, SEEK_END).
//
//________________________________________________________________________________________________________________________________________
 
s16 fseek_(File *file, s32 offset, s16 origin)
{
s32 fposition = 0;
s16 retvalue = 1;
u32 temp = 0;
 
//......................................................
if(origin == SEEK_SET) // Fileposition relative to the beginning of the file.
{
fposition = 0;
}
//......................................................
else if(origin == SEEK_END) // Fileposition relative to the end of the file.
{
fposition = (s32) file->filesize;
}
//......................................................
else if(origin == SEEK_CUR) // Fileposition relative to the current position of the file.
{
fposition = file->fileposition;
}
 
fposition += offset;
 
if((fposition >= 0) && (fposition <= (s32)file->filesize)) // is the pointer still within the file?
{
retvalue = 0;
file->sector_index = 0;
file->byte_index = 0;
file->fileposition = 0;
file->cluster_pointer = file->start_cluster;
 
while(file->fileposition < fposition)
{
file->fileposition++;
if(file->byte_index < 511)
{
file->byte_index++;
}
else
{
file->byte_index=0; // reading at the beginning of new sector.
file->sector_index++; // continue reading in next sector
if(file->sector_index >= SectorsPerCluster) // When end of cluster is reached, the next datacluster has to be searched in the FAT.
{
if(file->fileposition < fposition)
{
file->sector_index = 0; // start reading new cluster at first sector of the cluster.
GetNextCluster(file); // Sets the clusterpointer of the file to the next datacluster.
}
}
}
}
if(file->byte_index)
{
temp = (u32)((u32)file->cluster_pointer + (u32)file->sector_index);
SDC_GetSector((u32)temp,file->buffer); // FileBuffer will be written at once at the end of the cluster and has to be updated.
}
}
return(retvalue);
}
 
//________________________________________________________________________________________________________________________________________
// Funtion: fgetchar_(File *file);
//
// Description: This function reads and returns one character from the specified file.
//
// Returnvalue: The function returns the character read from the specified memorylocation as u8 casted to s16 or EOF.
//________________________________________________________________________________________________________________________________________
 
s16 fgetchar_(File *file)
{
s16 c = EOF;
u32 temp1;
 
if(file->filesize > 0) // wen the end of the file is not reached, get the next character.
{
temp1 = (u32)file->cluster_pointer; // calculate the adress of the next character to be read.
temp1 += (u32)file->sector_index;
 
if(file->sector_in_buffer != temp1) // Has the content of the buffer been modified and has to be updated?
{
SDC_GetSector((u32)temp1,file->buffer); // Read the calculated cluster.
file->sector_in_buffer = (u32)temp1;
}
c = (s16) file->buffer[file->byte_index];
file->filesize--; // decrement the number of characters available.
 
if(file->byte_index < 511) // continue reading from this sector until the end of the sector is reached.
{
file->byte_index++;
}
else // has the end of an sector been reached->
{
file->byte_index=0; // continue reading at the beginning -
file->sector_index++; // of new sector.
if(file->sector_index >= SectorsPerCluster) // When the end of an cluster is reached, the next datacluster has to be searched in the FAT.
{
file->sector_index = 0; // start reading new cluster at first sector of the cluster.
GetNextCluster(file); // Sets the clusterpointer of the file to the next datacluster.
}
}
}
return(c);
}
 
//________________________________________________________________________________________________________________________________________
// Funtion: fputchar_(File *file, s8 *);
//
// Description: This function writes a byte to the specified file and takes care of writing the necessary FAT- Entries.
//
// Returnvalue: The function returns a value of 0 if the data could not be written.
//________________________________________________________________________________________________________________________________________
 
u8 fputchar_(File *file,s8 c)
{
u32 ul_temp = 0;
u8 retvalue = 1;
 
if(file->sector_index >= SectorsPerCluster) // if end of the cluster is reached, find next free cluster
{
file->sector_index = 0;
if(!AppendCluster(file)) retvalue = 0; // append a new and free cluster at the end of the file.
}
 
file->buffer[file->byte_index] = c; // write databyte into the buffer. The byte will be written to the device at once
if(file->filesize == file->fileposition) file->filesize++; // a character has been written to the file so the size is inkremented but only when the character has been added at the end of the file.
file->fileposition++; // the actual positon within the file.
// if the buffer contains the complete sectordata.
if(file->byte_index < 511) // if the end of this sector is not reached yet
{
file->byte_index++; // the next byte will be written to the next byteposition in this sector.
}
else // otherwise the data in the sectorbuffer will be written to the device and the next sector will be selected.
{
ul_temp = (u32)file->cluster_pointer;
ul_temp += (u32)file->sector_index;
 
SDC_PutSector((u32)ul_temp,file->buffer);
file->byte_index=0; // and the next byte will be written at the beginning of this new sector.
file->sector_index++;
if(file->sector_index >= SectorsPerCluster) // if end of the cluster is reached, find next free cluster
{
file->sector_index = 0;
if(!AppendCluster(file)) retvalue = 0; // append a new and free cluster at the end of the file.
}
}
return(retvalue);
}
 
//________________________________________________________________________________________________________________________________________
// Funtion: fputs_(File *file, s8 *string);
//
// Description: This function writes a string to the specified file.
//
//________________________________________________________________________________________________________________________________________
 
u8 fputs_(File *file,s8 * string)
{
u8 i=0;
 
while(string[i] != 0)
{
fputchar_(file,string[i]);
i++;
}
return(0);
}
 
//________________________________________________________________________________________________________________________________________
// Funtion: s8 * fgets_(s8 *string, s16 count, File *file)
//
// Description: This function reads a string from the file to the specifies string.
//
// Returnvalue: A pointer to the string written from the file.
//________________________________________________________________________________________________________________________________________
 
s8 * fgets_(s8 *string, s16 count, File *file)
{
s16 buff_pnt = 0;
s16 buff_tmp = 0;
u8 state = 0; // Variable used for a statemachine to recognize the end of a line.
 
while(count > 1) // read the count-1 characters from the file to the string.
{
buff_tmp = fgetchar_(file); // read a character from the opened file.
switch(state)
{
case 0:
if(buff_tmp == 0x0D) state++;
break;
 
case 1:
if(buff_tmp == 0x0A)
{
count = 1;
}
state = 0;
break;
}
if(buff_tmp == EOF) {buff_tmp = 0; count = 1;} // is the end of the file reached, terminate the string with zero.
string[buff_pnt] = (s8) buff_tmp;
count--;
buff_pnt++;
}
string[buff_pnt] = 0;
return(string);
}
 
//________________________________________________________________________________________________________________________________________
// Funtion: u8 fexist_(u8*, File *file);
//
// Description: This function searches the specified file and returns 0 if the file was not found.
//
//
// Return: 0 = file does not exist
// 1 = file exists
//________________________________________________________________________________________________________________________________________
 
u8 fexist_(s8 *fname)
{
File *file;
 
file = ReserveFilePointer();
 
if(file != NULL)
{
if((file = fopen_(fname,'r'))!= NULL)
{
fclose_(file);
return(1);
}
else
{
return(0);
}
}
else
{
return(0);
}
}
 
//________________________________________________________________________________________________________________________________________
// Funtion: GetNextCluster(File *file);
//
// Description: This function finds the next datacluster of the file specified with File *file.
//
// Returnvalue: The function returns "0" if the last cluster has already been reached.
//________________________________________________________________________________________________________________________________________
 
u16 GetNextCluster(File *file)
{
u32 fat_pointer = 0;
u32 fat_sector_offset = 0;
u32 ul_tmp = 0;
u8 retvalue = 0; // no new cluster found yet.
 
 
if((file->cluster_pointer >= RootDirectory) && (file->cluster_pointer < (RootDirectory + 31)))
{ // Is the next cluster searched within the rootdirectory and available?
file->cluster_pointer++; // the rootdirectory is a linear adress space of 32 clusters.
retvalue = 1; // and the next cluster has been found.
}
else if(file->cluster_pointer > (RootDirectory + 31)) // The specified cluster is within the FAT.
{
fat_sector_offset = ((file->cluster_pointer) - (FirstDataCluster)); // Calculate index of actual cluster within the FAT.
fat_sector_offset /= SectorsPerCluster; // calculate the index of the actual sector within the FAT.
fat_sector_offset += 2; // In Fat16 clusterpositions have an offset of two.
fat_pointer = (fat_sector_offset%0x100); // Calculate the sector within the cluster.
fat_sector_offset = (fat_sector_offset>>8); // and the position within the sector.
 
SDC_GetSector((u32)(FileAllocationTable + fat_sector_offset),file->buffer);
file->sector_in_buffer = (FileAllocationTable + fat_sector_offset); // Mark that new sector has been read.
 
ul_tmp = (u32)file->buffer[((fat_pointer << 1)+1)]; // Read next sector information from calculated clusterposition.
ul_tmp = (ul_tmp << 8);
ul_tmp |= (u32)file->buffer[(fat_pointer << 1)];
ul_tmp -=2; // next datacluster is clusterposition in fat - 2.
ul_tmp *= SectorsPerCluster; // calculate sectorposition of new cluster
ul_tmp += FirstDataCluster; // in relation to first datacluster of the disk.
 
if(ul_tmp < 0xfff7) // has a new cluster been read or was the end of the fat reached?
{
file->cluster_pointer = (u32) ul_tmp; // continue reading the file at the beginning of new datacluster.
retvalue = 1; // a new cluster was found.
}
}
return(retvalue);
}
 
//________________________________________________________________________________________________________________________________________
// Funtion: u16 FindNextFreeCluster(void)
//
// Description: This function looks in the FAT to find the next free datacluster
//
// Returnvalue: The function returns the adress of the next free cluster found within the fAT.
//________________________________________________________________________________________________________________________________________
 
u16 FindNextFreeCluster(File *file)
{
u32 fat_pointer = 0; // Pointer to the first sector of the FAT.
u32 ul_tmp = 0; // temporary variable used to calculate a sectornumber.
u16 fat_sector_offset = 0; // index to a sector within the FAT.
u16 fat_entry = 0; // index to an fatentry within the actual sector (256 fatentries are possible within one sector).
u16 free_cluster = 0; // a pointer to the first sector of the next free cluster.
 
fat_pointer = (u32) FileAllocationTable; // start searching for empty cluster at the beginning of the fat.
// if the end of the fat is not reached yet and no free cluster has been found
while((fat_sector_offset < SectorsPerFat) && (!free_cluster))
{
ul_tmp = (u32) ((u32)fat_pointer + (u32)fat_sector_offset);
SDC_GetSector((u32)ul_tmp,file->buffer); // read next sector of FAT.
file->sector_in_buffer = ul_tmp; // remember the number of the sector in FileBuffer.
Fat = (struct FatEntry *)file->buffer;
for(fat_entry=0;fat_entry<256;fat_entry++) // look for an free cluster at all entries in this sector of the fat.
{
if(Fat[fat_entry].next_cluster == 0x0000) // empty cluster found!!
{
Fat[fat_entry].next_cluster = 0xffff; // mark this fat-entry as used and save it to the device.
SDC_PutSector((u32)file->sector_in_buffer,file->buffer);
free_cluster = fat_entry; // the relative position of the free cluster found in this sector of the FAT.
free_cluster += (fat_sector_offset << 8); // calculate the absolute position of the free cluster in the FAT;
fat_entry = 256; // terminate the search for a free cluster in this sector.
}
}
fat_sector_offset++;
}
return(free_cluster);
}
 
//________________________________________________________________________________________________________________________________________
// Funtion: u16 AppendCluster(File *file);
//
// Description: This function finds the next free datacluster on the disk and appends it to the specified file.
//
// Returnvalue: This funktion returns 1 if a cluster was appended to the specified file.
//________________________________________________________________________________________________________________________________________
 
u8 AppendCluster(File *file)
{
u16 free_cluster = 0;
u32 fat_pointer = 0;
u8 retvalue = 0;
 
free_cluster = FindNextFreeCluster(file); // the next free cluster found on the disk.
if(free_cluster) retvalue = 1; // A free cluster was found and can be added to the end of the file.
fat_pointer = FileAllocationTable; // Set Pointer to the beginnig of the FAT.
fat_pointer += (u32)((u32)GetFatClusterOffset(file) >> 8); // find the sector in the FAT with 256 entries per sector.
 
SDC_GetSector(fat_pointer,file->buffer);
Fat = (struct FatEntry *)file->buffer;
Fat[GetFatSectorIndex(file)].next_cluster = free_cluster; // append the free cluster to the end of the file in the FAT.
SDC_PutSector((u32)fat_pointer,file->buffer); // save the modified sector to the FAT.
 
fat_pointer = (u32)free_cluster;
fat_pointer -= 2;
fat_pointer *= SectorsPerCluster;
fat_pointer += FirstDataCluster;
 
file->cluster_pointer = fat_pointer; // continue wrtiting to the file in the new and free datacluster.
return(retvalue); // return 1 when a new cluster was appended to the file
}
 
 
//________________________________________________________________________________________________________________________________________
// Funtion: void DeleteClusterChain(u16 startcluster);
//
// Description: This function frees all the clusters used for file from the fat.
//
// Returnvalue: none
//________________________________________________________________________________________________________________________________________
 
void DeleteClusterChain(u16 startcluster)
{
u16 fat_index = 0;
u16 fat_sector_offset = 0;
u32 sector_in_buffer = 0;
u32 ul_temp = 0;
u8 buffer[512];
 
fat_index = (startcluster % 0x100); // Calculate the sector within the cluster.
fat_sector_offset = (startcluster >> 8); // and the position within the sector.
ul_temp = (u32)(FileAllocationTable + fat_sector_offset);
 
 
do
{
if(sector_in_buffer != ul_temp)
{
sector_in_buffer = ul_temp;
SDC_GetSector(ul_temp,buffer);
}
Fat = (struct FatEntry *)buffer;
 
startcluster = Fat[fat_index].next_cluster;
Fat[fat_index].next_cluster = 0x0000; // free the cluster within the fat.
 
fat_index = (startcluster % 0x100); // Calculate the sector within the cluster.
fat_sector_offset = (startcluster >> 8); // and the position within the sector.
ul_temp = (u32)(FileAllocationTable + fat_sector_offset);
if((sector_in_buffer != ul_temp) || (startcluster == 0xffff))
{
SDC_PutSector(sector_in_buffer,buffer);
}
}
while(startcluster != 0xffff); // last cluster has been deleted.
}
 
 
//________________________________________________________________________________________________________________________________________
// Funtion: u16 GetFatClusterIndex(File *file);
//
// Description: This function returns the clusterindex of the cluster specified by file->cluster_pointer of the specified file.
//
//________________________________________________________________________________________________________________________________________
 
u16 GetFatClusterOffset(File *file)
{
u32 fat_sector_offset = 0;
 
fat_sector_offset = ((file->cluster_pointer) - (FirstDataCluster)); // Calculate index of actual cluster in FAT.
fat_sector_offset /= SectorsPerCluster;
fat_sector_offset += 2; // In Fat16 clusterpositions have an offset of two.
 
return((u16)fat_sector_offset);
}
 
//________________________________________________________________________________________________________________________________________
// Funtion: u16 GetFatSectorIndex(File *file);
//
// Description: This function returns the sectorindex of the cluster specified by file->cluster_pointer of the specified file.
//
//________________________________________________________________________________________________________________________________________
 
u16 GetFatSectorIndex(File *file)
{
u16 fat_pointer = 0;
 
fat_pointer = GetFatClusterOffset(file);
fat_pointer = fat_pointer % 0x100; // Calculate the clusterposition in the fat
 
return(fat_pointer);
}
 
//________________________________________________________________________________________________________________________________________
// Funtion: u16 CreateFileInDirectory(u8 *, File *)
//
// Description: This function looks for the next free position in the directory and creates an entry. The type of an directoryentry is
// specified by the attribute.
// bit0: unused
// bit1: archive
// bit2: read_only
// bit3: system
// bit4: directory
// bit5: volume
//________________________________________________________________________________________________________________________________________
 
u8 CreateFileInDirectory(s8 *fname, File *file)
{
u16 rootentry = 0; // index to an entry in the rootdirectory.
u16 cnt_enries_searched = 0; // count the number of rootentries which have been searched already.
u8 i = 0;
u16 sector_offset = 0; // index to the sector of the Rootentry which is searched momentarily
u8 retvalue = 0;
u32 cluster_temp = 0;
u16 cluster = 0;
s8 name[11] = " ";
 
SeperateFileName(fname,name);
 
cluster_temp = (u32)FindNextFreeCluster(file); // the next free cluster on the disk.
 
if(cluster_temp) // if a free cluster is available:
{
cluster = (u16)cluster_temp; // remember the index of the free datacluster found for the directory entry.
cluster_temp -=2; // Clusterposition is ((position in FAT)-2). first two entries in FAT are reserved.
cluster_temp *= SectorsPerCluster; // Calculate relative sectorindex of first datacluster.
file->start_cluster = (FirstDataCluster + cluster_temp); // Calculate absolute sectorposition of first datacluster.
file->cluster_pointer = file->start_cluster; // start reading the file with the first sector of the first datacluster.
 
// directory starts at sector specified by dir_sector. This can be the rootdirectory or any other directory.
do
{ // search the next 16 rootentries in this sector of the roordirectory.
rootentry=0;
SDC_GetSector((u32)(CWD + sector_offset),file->buffer); // Read the Rootdirectory.
DirectoryEntry = (struct DirEntry *)file->buffer;
while((rootentry<16) && (!retvalue))
{
if((DirectoryEntry[rootentry].attribute == 0) || (DirectoryEntry[rootentry].attribute == 0xE5)) // empty directory entry found
{
for(i=0;i<11;i++) DirectoryEntry[rootentry].name[i] = name[i]; // Kopie the filename and the file extension to the directoryentry.
DirectoryEntry[rootentry].attribute = _FILE; // Set the fileattribute to archive to reserve the directoryentry.
DirectoryEntry[rootentry].startcluster = cluster; // copy the location of the first datacluster to the directoryentry.
DirectoryEntry[rootentry].size = 0; // the new createted file has no content yet.
file->directory_sector = (u32) (CWD + sector_offset);
file->directory_index = (u8) rootentry;
retvalue = 1;
SDC_PutSector((u32)(CWD + sector_offset),file->buffer);
}
rootentry++;
cnt_enries_searched++;
}
if(!retvalue) // file not found in this sector so take next sector.
{
rootentry = 0;
sector_offset++;
}
}
while((cnt_enries_searched< PossibleRootEntries) && (!retvalue));
 
}
return(retvalue); // return 1 if file has been created otherwise return 0.
}
 
//________________________________________________________________________________________________________________________________________
// Funtion: u16 SeekFileInDirectory(s8 *fname, File *)
//
// Description: this function searches all possible entries withint the actual directory for the specified object.
//
// Returnvalue: This function returns 1 if the directoryentry specified was found.
//________________________________________________________________________________________________________________________________________
 
u8 SeekFileInDirectory(s8 *fname, File *file)
{
u16 rootentry=0;
u16 end_of_directory_not_reached = 0; // the directory has been read completely without a result.
u8 i=0;
u8 retvalue = 0;
u32 cluster_temp = 0;
s8 name[11] = " ";
 
SeperateFileName(fname,name);
 
file->cluster_pointer = CWD; // start looking for the file in the actual directory.
 
// directory starts at sector specified by dir_sector. This can be the rootdirectory or any other directory.
do
{ // search the next 16 rootentries in this sector of the roordirectory.
rootentry=0;
SDC_GetSector((u32) file->cluster_pointer,file->buffer); // Read the Rootdirectory.
DirectoryEntry = (struct DirEntry *)file->buffer;
 
while((!retvalue)&&(rootentry<16))
{
i=0;
if(DirectoryEntry[rootentry].name[0] != 0xe5) // ignore deleted items.
{
while((i<=10)&&(DirectoryEntry[rootentry].name[i] == name[i]))
{
i++;
}
}
 
if((i==11) && (DirectoryEntry[rootentry].attribute & _FILE)) // entry found!! -> reading startcluster of entry from offset 26.
{
cluster_temp = (u32)DirectoryEntry[rootentry].startcluster;
cluster_temp -=2; // Clusterposition is ((position in FAT)-2). first two entries in FAT are reserved.
cluster_temp *= (u32)SectorsPerCluster; // Calculate positon of first cluster.
file->start_cluster = (FirstDataCluster + cluster_temp);
file->directory_sector = (u32) file->cluster_pointer;
file->cluster_pointer = file->start_cluster; // start reading the file with the first cluster.
file->filesize = (u32) DirectoryEntry[rootentry].size;
file->directory_index = (u8) rootentry;
retvalue = 1;
}
rootentry++;
}
if(!retvalue) // file not found in this sector so take next sector.
{
end_of_directory_not_reached = GetNextCluster(file);
}
}
while((end_of_directory_not_reached) && (!retvalue));
return(retvalue);
}
 
 
 
//________________________________________________________________________________________________________________________________________
// Funtion: void SeperateFileName(u8*);
//
// Description: This function seperates the filename and the fileattribute and brings them into the needed format ('test.txt' -> 'TEST TXT');
//
//________________________________________________________________________________________________________________________________________
 
void SeperateFileName(s8 *fname, s8 *name)
{
u8 readpointer = 0;
u8 writepointer = 0;
u8 attribute = 1;
u8 i = 0;
 
 
while((writepointer<=10) && (fname[readpointer]!=0)) // the rootdirectoryentry is 8bytes for filename and 3bytes for fileattribute.
{ // the filename in the rootdirectory is in the format "TEST TXT" without the dot.
if(fname[readpointer]=='.') // seperating filename and attribute.
{
if(attribute) // is the filename "." or ".." ?
{
name[writepointer] = fname[readpointer];
readpointer++;
writepointer++;
}
else
{
if(fname[(readpointer-1)] != '*')
{
for(i=writepointer;i<8;i++)
{
name[i] = ' ';
}
}
readpointer++;
writepointer = 8;
}
}
else if(fname[readpointer] == '*') // wildcard found within the filename + extension.
{
if(writepointer < 8) // in extension.
{
readpointer++;
writepointer = 8;
}
else // in filename.
{
writepointer = 11; // jump to the end of the string to terminate this function.
}
attribute = 0;
}
else
{
if((fname[readpointer]>96) && (fname[readpointer]<123))
{
name[writepointer]=(fname[readpointer] - 32); // all characters must be upper case.
}
else
{
name[writepointer]=fname[readpointer];
}
readpointer++;
writepointer++;
attribute = 0;
}
}
}
 
//________________________________________________________________________________________________________________________________________
// Funtion: File * ReserveFilePointer_(void);
//
// Description: This function looks for a free filepointer and reserves it.
//
//
// Return: NULL = faild to reserve a filepointer
// otherwise filepointer
//________________________________________________________________________________________________________________________________________
 
File * ReserveFilePointer(void)
{
File *file;
file = NULL;
u8 temp;
 
for(temp = 0;temp<__MAX_FILES_USED;temp++)
{
if(FilePointer[temp].state == _UNUSED) // free filepointer found?
{
file = &FilePointer[temp];
FilePointer[temp].state = _USED; // mark as used.
FilePointer[temp].mode = 0; // type of access (read/write) not defined yet.
FilePointer[temp].start_cluster = 0; // Sectorpointer to the first sector of the first datacluster of the file.
FilePointer[temp].cluster_pointer = 0; // Pointer to the cluster which is edited at the moment.
FilePointer[temp].sector_index = 0; // The sector which is edited at the moment (cluster_pointer + sector_index).
FilePointer[temp].byte_index = 0; // The bytelocation within the current sector (cluster_pointer + sector_index + byte_index).
FilePointer[temp].filesize = 0; // the size of the opend file in bytes.
FilePointer[temp].fileposition = 0; // pointer to a character within the file 0 < fileposition < filesize
FilePointer[temp].sector_in_buffer = 0; // the last sector read, wich is still in the sectorbuffer.
FilePointer[temp].directory_sector = 0; // the sectorposition where the directoryentry has been made.
FilePointer[temp].directory_index = 0; // the index to the directoryentry within the specified sector.
FilePointer[temp].attribute = 0; // the attribute of the file opened.
break;
}
}
return(file);
}
 
 
//________________________________________________________________________________________________________________________________________
// Funtion: void FreeFilePointer_(File *);
//
// Description: This function free's the filepointer by marking it as unused.
//
//
// Return: none
//
//________________________________________________________________________________________________________________________________________
 
void FreeFilePointer(File *file)
{
u8 cnt = 0;
 
for(cnt=0;cnt<__MAX_FILES_USED;cnt++) // Is the filepointeradress vaild?
{
if(&FilePointer[cnt] == file) // filepointer found therefore it must be valid
{
FilePointer[cnt].state = _UNUSED; // and can be marked as unused.
}
}
}
 
 
//________________________________________________________________________________________________________________________________________
// Funtion: void DelteDirectoryEntry(Find *)
//
// Description: This function deletes the directoryentry of the specified item.
//
//
// returnvalue: 1 if the directory could be created.
//________________________________________________________________________________________________________________________________________
 
void DeleteDirectoryEntry(Find *item)
{
u8 buffer[512];
 
 
SDC_GetSector((u32) item->cluster_pointer,buffer); // Read the Rootdirectory.
DirectoryEntry = (struct DirEntry *)buffer;
 
DirectoryEntry[(item->directory_index)-1].attribute = 0; // free the directoryentry.
DirectoryEntry[(item->directory_index)-1].name[0] = 0xE5; // free the directoryentry.
SDC_PutSector((u32) item->cluster_pointer,buffer); // Read the Rootdirectory.
}
 
 
 
 
//________________________________________________________________________________________________________________________________________
// Funtion: u8 CreateSubDirectory(u8 *)
//
// Description: This function creates an directory within the directory specified by CWD
//
//
// returnvalue: 1 if the directory could be created.
//________________________________________________________________________________________________________________________________________
 
u8 CreateSubDirectory(s8 *fname)
{
u16 index = 0; // index to an entry in the rootdirectory.
u16 cnt_entries_searched = 0; // count the number of rootentries which have been searched already.
u16 i = 0;
u16 sector_offset = 0; // index to the sector of the entry which is searched momentarily
u8 retvalue = 0;
u32 cluster_temp = 0;
u16 cluster = 0;
File file;
u8 name[11] = {" "};
 
SeperateFileName(fname,name);
cluster_temp = (u32)FindNextFreeCluster(&file); // the next free cluster on the disk.
 
if(cluster_temp) // if a free cluster is available:
{
cluster = (u16)cluster_temp; // remember the index of the free datacluster found for the directory entry.
cluster_temp -=2; // Clusterposition is ((position in FAT)-2). first two entries in FAT are reserved.
cluster_temp *= SectorsPerCluster; // Calculate relative sectorindex of first datacluster.
file.start_cluster = (FirstDataCluster + cluster_temp); // Calculate absolute sectorposition of first datacluster.
file.cluster_pointer = file.start_cluster; // start reading the file with the first sector of the first datacluster.
 
// -Initialise new cluster to zero--------------------------------------------------------
for(i=0;i<512;i++)
{
file.buffer[i] = 0; // initialise buffer to zero
}
for(sector_offset=0;sector_offset<SectorsPerCluster;sector_offset++) // initialise all sectors of new cluster with buffer.
{
SDC_PutSector((u32)(file.start_cluster + sector_offset),file.buffer); // save the initialised sector to the card.
}
// -Create directoryentry "." -------------------------------------------------------------
DirectoryEntry = (struct DirEntry *)file.buffer;
DirectoryEntry[0].name[0] = '.';
DirectoryEntry[0].attribute = _DIRECTORY;
DirectoryEntry[0].startcluster = cluster;
// -Create directoryentry "." -------------------------------------------------------------
DirectoryEntry[1].name[0] = '.';
DirectoryEntry[1].name[1] = '.';
DirectoryEntry[1].attribute = _DIRECTORY;
if(CWD == RootDirectory)
{
DirectoryEntry[1].startcluster = 0;
}
else
{
cluster_temp = (CWD - FirstDataCluster);
cluster_temp /= SectorsPerCluster;
cluster_temp -= 2;
DirectoryEntry[1].startcluster = (u16) cluster_temp;
}
SDC_PutSector((u32) file.start_cluster,file.buffer); // save the initialised sector to the card.
// -create directoryentry within the cwd --------------------------------------------------
sector_offset = 0;
cnt_entries_searched = 0;
do
{ // search the next 16 rootentries in this sector of the roordirectory.
index=0;
SDC_GetSector((u32)(CWD + sector_offset),file.buffer); // Read the actual directory.
DirectoryEntry = (struct DirEntry *)file.buffer;
while((index<16) && (!retvalue))
{
if((DirectoryEntry[index].attribute == 0) || (DirectoryEntry[index].attribute == 0xE5)) // empty directory entry found
{
for(i=0;i<11;i++) DirectoryEntry[index].name[i] = name[i]; // Kopie the filename and the file extension to the directoryentry.
DirectoryEntry[index].attribute = _DIRECTORY; // Set the fileattribute to archive to reserve the directoryentry.
DirectoryEntry[index].startcluster = cluster; // copy the location of the first datacluster to the directoryentry.
DirectoryEntry[index].size = 0; // the new createted file has no content yet.
file.directory_sector = (u32) (CWD + sector_offset);
file.directory_index = (u8) index;
retvalue = 1;
SDC_PutSector((u32)(CWD + sector_offset),file.buffer);
}
index++;
cnt_entries_searched++;
}
if(!retvalue) // file not found in this sector so take next sector.
{
index = 0;
sector_offset++;
}
}
while((cnt_entries_searched< PossibleRootEntries) && (!retvalue));
 
}
return(retvalue); // return 1 if file has been created otherwise return 0.
}
 
 
//________________________________________________________________________________________________________________________________________
// Funtion: u16 SeekSubDirectory(s8 *fname)
//
// Description: looks for the specified directory within the CWD.
//
// Returnvalue: If the specified directory was found the startcluster is returned. otherwise 0.
//________________________________________________________________________________________________________________________________________
 
u16 SeekSubDirectory(s8 *fname)
{
u16 index = 0;
u16 end_of_directory_not_reached = 0; // the directory has been read completely without a result.
u8 i = 0;
u16 cluster_temp = 0;
s8 name[11] = " ";
File file;
 
SeperateFileName(fname,name);
 
file.cluster_pointer = CWD; // start looking for the file in the actual directory.
file.start_cluster = CWD; // start looking for the file in the actual directory.
 
// directory starts at sector specified by dir_sector. This can be the rootdirectory or any other directory.
do
{ // search the next 16 rootentries in this sector of the roordirectory.
index=0;
SDC_GetSector((u32) file.cluster_pointer,file.buffer); // Read the Rootdirectory.
DirectoryEntry = (struct DirEntry *)file.buffer;
 
while((!cluster_temp)&&(index<16))
{
i=0;
if(DirectoryEntry[index].name[0] != 0xe5) // ignore deleted items.
{
while((i<=10)&&(DirectoryEntry[index].name[i] == name[i]))
{
i++;
}
}
 
if((i==11) && (DirectoryEntry[index].attribute & _DIRECTORY)) // entry found!! -> reading startcluster of entry from offset 26.
{
cluster_temp = (u16)DirectoryEntry[index].startcluster;
}
index++;
}
if(!cluster_temp) // file not found in this sector so take next sector.
{
end_of_directory_not_reached = GetNextCluster(&file);
}
}
while((end_of_directory_not_reached) && (!cluster_temp));
return(cluster_temp);
}
 
 
 
//________________________________________________________________________________________________________________________________________
// Funtion: u8 mkdir_(u8 *)
//
// Description: This function checks if the directory to be created already exists. If not the directory will be created.
//
//
// returnvalue: 1 if the directory could be created.
//________________________________________________________________________________________________________________________________________
 
u8 mkdir_(s8 *fname)
{
u8 retvalue = 0;
 
retvalue = SeekSubDirectory(fname); // check wether the specified directory already exists.
 
if(!retvalue)
{
CreateSubDirectory(fname); // if directory doesn't exist, create it.
retvalue = 1;
}
else
{
retvalue = 0;
}
 
return(retvalue);
}
 
 
//________________________________________________________________________________________________________________________________________
// Funtion: u8 chdir_(u8 *)
//
// Description: This function changes the CWD to the directory specified.
//
//
// returnvalue: 1 if the directory could be changed.
//________________________________________________________________________________________________________________________________________
 
u8 chdir_(s8 *fname)
{
u8 retvalue = 0;
u8 name[11] = {" "};
 
u32 ultemp = 0;
 
SeperateFileName(fname,name);
 
ultemp = (u32)SeekSubDirectory(name);
if(ultemp >= 2)
{
ultemp -=2; // Clusterposition is ((position in FAT)-2). first two entries in FAT are reserved.
ultemp *= SectorsPerCluster; // Calculate relative sectorindex of first datacluster.
ultemp += FirstDataCluster;
CWD = ultemp;
retvalue = 1;
}
else
{
CWD = RootDirectory;
retvalue = 1;
}
 
return(retvalue);
}
 
 
//________________________________________________________________________________________________________________________________________
// Funtion: u8 FindItem(s8 *fname, Find *)
//
// Description: finds an item (file or directory) within common working directory (cwd). Wildcards '*' or '?' will be considered.
//
// Returnvalue: If an item was found this function returns '1' else '0'.
//________________________________________________________________________________________________________________________________________
 
u8 FindItem(Find *item)
{
u16 index = 0;
u16 end_of_directory_not_reached = 0; // the directory has been read completely without a result.
u8 i = 0;
u8 readpointer = 0;
u8 writepointer = 0;
u8 retvalue = 0;
File file;
 
 
file.cluster_pointer = item->cluster_pointer;
file.start_cluster = item->cluster_pointer;
index = item->directory_index;
// directory starts at sector specified by dir_sector. This can be the rootdirectory or any other directory.
do
{ // search the next 16 rootentries in this sector of the roordirectory.
SDC_GetSector((u32) file.cluster_pointer,file.buffer); // Read the Rootdirectory.
DirectoryEntry = (struct DirEntry *)file.buffer;
 
while((!retvalue)&&(index<16))
{
i=0;
if(DirectoryEntry[index].name[0] != 0xe5) // ignore deleted items.
{
while((i<=10)&&((DirectoryEntry[index].name[i] == item->searchstring[i]) || (item->searchstring[i]=='*') || item->searchstring[i]=='?'))
{
i++;
}
}
 
if((i==11) && (DirectoryEntry[index].attribute & item->attribute))
{
for(readpointer=0;readpointer<=10;readpointer++)
{
if(DirectoryEntry[index].name[readpointer] != ' ')
{
item->name[writepointer] = DirectoryEntry[index].name[readpointer]; // copy the name of the item found to the find_structure.
writepointer++;
}
else if((readpointer==7) && (DirectoryEntry[index].attribute == _FILE)) // if the item found is a file
{
if(DirectoryEntry[index].name[readpointer] != ' ')
{
item->name[writepointer] = DirectoryEntry[index].name[readpointer]; // copy the name of the item found to the find_structure.
writepointer++;
}
item->name[writepointer] = '.'; // then seperate the name and the extension by a '.' at index 8.
writepointer++;
}
}
item->startcluster = (u16)DirectoryEntry[index].startcluster;
item->directory_index = ++index;
item->cluster_pointer = file.cluster_pointer;
retvalue = 1;
}
index++;
}
if(!retvalue) // file not found in this sector so take next sector.
{
end_of_directory_not_reached = GetNextCluster(&file);
}
index = 0;
}
while((end_of_directory_not_reached) && (!retvalue));
 
return(retvalue);
}
 
 
//________________________________________________________________________________________________________________________________________
// Funtion: u8 findfirst(s8 *fname, Find *)
//
// Description: finds the first item (file or directory) within common working directory (cwd). Wildcards '*' or '?' will be considered.
//
// Returnvalue: If an item was found this function returns '1' else '0'.
//________________________________________________________________________________________________________________________________________
 
u8 findfirst_(s8 *fname, Find *item, u8 attribute)
{
u8 retvalue = 0;
u8 i = 0;
 
for(i=0;i<=11;i++)
{
item->searchstring[i] = '*'; // initialise the searchstring with wildcards.
item->name[i] = 0;
}
 
SeperateFileName(fname,item->searchstring);
 
item->cluster_pointer = CWD; // findfirst_ starts at the beginning of the cwd.
item->directory_index = 0;
item->attribute = attribute;
 
retvalue = FindItem(item);
 
return(retvalue);
}
 
 
//________________________________________________________________________________________________________________________________________
// Funtion: u8 findnext(Find *)
//
// Description: finds the first item (file or directory) within common working directory (cwd). Wildcards '*' or '?' will be considered.
//
// Returnvalue: If an item was found this function returns '1' else '0'.
//________________________________________________________________________________________________________________________________________
 
 
u8 findnext_(Find *item)
{
u8 retvalue = 0;
u8 i = 0;
 
for(i=0;i<=11;i++)
{
item->name[i] = 0;
}
 
retvalue = FindItem(item);
 
return(retvalue);
}
 
 
 
//________________________________________________________________________________________________________________________________________
// Funtion: u8 fdelete(s8 *fname)
//
// Description: Deletes the file specified by fname.
//
// Returnvalue:
//________________________________________________________________________________________________________________________________________
 
 
u8 fdelete_(s8 *fname)
{
u8 retvalue = 0;
Find item;
 
printf("\n\rDeleting file");
retvalue = findfirst_(fname,&item, _FILE); // look for the item to be deleted.
 
if(retvalue); // item found?
{
printf("\n\r");
printf("%s", item.name);
 
DeleteClusterChain(item.startcluster); // delete all fatentries of the item.
DeleteDirectoryEntry(&item); // free the directoryentry.
 
do
{
printf("\n\r");
printf("%s", item.name);
retvalue = findnext_(&item);
if(retvalue)
{
DeleteClusterChain(item.startcluster); // delete all fatentries of the item.
DeleteDirectoryEntry(&item); // free the directoryentry.
}
}
while(retvalue);
}
 
printf("\n\rDone");
 
return(retvalue);
}
 
 
 
//________________________________________________________________________________________________________________________________________
// Funtion: u8 rmdir(s8 *fname)
//
// Description: Deletes the directory specified by dname.
//
// Returnvalue:
//________________________________________________________________________________________________________________________________________
 
 
u8 rmdir_(s8 *dname)
{
u8 retvalue = 0;
Find item;
 
printf("\n\rDeleting folder");
retvalue = findfirst_(dname,&item, _DIRECTORY); // look for the item to be deleted.
 
if(retvalue); // item found?
{
printf("\n\r");
printf("%s", item.name);
 
DeleteClusterChain(item.startcluster); // delete all fatentries of the item.
DeleteDirectoryEntry(&item); // free the directoryentry.
 
do
{
printf("\n\r");
printf("%s", item.name);
retvalue = findnext_(&item);
if(retvalue)
{
DeleteClusterChain(item.startcluster); // delete all fatentries of the item.
DeleteDirectoryEntry(&item); // free the directoryentry.
}
}
while(retvalue);
}
 
printf("\n\rDone");
 
return(retvalue);
}
 
/FollowMe/fat16.h
0,0 → 1,267
#ifndef __fat16_h
#define __fat16_h
 
 
 
 
 
//________________________________________________________________________________________________________________________________________
//
// Userspecific definitions
//
//________________________________________________________________________________________________________________________________________
 
#define __MAX_FILES_USED 1 // The number of files that can be opened simultaneously.
 
 
 
 
 
 
 
 
//________________________________________________________________________________________________________________________________________
//
// Datatype definitions
//
//________________________________________________________________________________________________________________________________________
 
typedef unsigned char u8;
typedef signed char s8;
typedef unsigned short u16;
typedef signed short s16;
typedef unsigned long u32;
typedef signed long s32;
 
 
 
//________________________________________________________________________________________________________________________________________
//
// Structure of a filepointer
//
//________________________________________________________________________________________________________________________________________
 
#define _UNUSED 1 // Bits used in the attribute of an directory entry.
#define _USED 2
#define _ARCHIVE 2
#define _READ_ONLY 4
#define _SYSTEM 8
#define _DIRECTORY 16
#define _FILE 32
 
 
typedef struct afile
{
u32 start_cluster; // Sectorpointer to the first sector of the first datacluster of the file.
u32 cluster_pointer; // Pointer to the cluster which is edited at the moment.
u8 sector_index; // The sector which is edited at the moment (cluster_pointer + sector_index).
u16 byte_index; // The bytelocation within the current sector (cluster_pointer + sector_index + byte_index).
u8 mode; // mode of fileoperation (read,write)
u32 filesize; // the size of the opend file in bytes.
u32 fileposition; // pointer to a character within the file 0 < fileposition < filesize
u32 sector_in_buffer; // the last sector read, wich is still in the sectorbuffer.
u32 directory_root_sector; // pointer to the root of the
u32 directory_sector; // the sectorposition where the directoryentry has been made.
u8 directory_index; // the index to the directoryentry within the specified sector.
u8 attribute; // the attribute of the file opened.
u8 buffer[512]; // Buffer for read and write operation from or to the mmc.
u8 state; // state of the filepointer (used/unused/...)
} File;
 
//________________________________________________________________________________________________________________________________________
//
// Structure of an item to find within the cwd
//
//________________________________________________________________________________________________________________________________________
 
typedef struct find
{
u8 name[12]; // filename + extension or directoryname of the item found within the cwd.
u8 searchstring[13];
u32 cluster_pointer; // Sectorpointer to the sector of the item searched within the cwd.
u16 startcluster; // pointer to the first datacluster of the item found in the cwd.
u32 filesize; // the size of the opend file in bytes.
u32 directory_sector; // the sector within the actual cluster where the directoryentry was found.
u8 directory_index; // the index to the directoryentry within the specified sector.
u8 attribute; // the attribute of the file opened.
} Find;
 
//________________________________________________________________________________________________________________________________________
//
// Directoryentries
//
//________________________________________________________________________________________________________________________________________
 
 
 
struct DirEntry
{
u8 name[8]; // 8 bytes name.
u8 extension[3]; // 3 bytes extension.
u8 attribute; // attribute of the directory entry (unused,archive,read-only,system,directory,volume)
u8 reserved[10]; // reserved bytes within the directory entry.
u16 time; // time and
u16 date; // date of last write acces to the file or directory.
u16 startcluster; // first cluster of the file or directory.
u32 size; // size of the file or directory in bytes.
} __attribute__((packed));
 
//________________________________________________________________________________________________________________________________________
//
// Structure of an entry within the fileallocationtable.
//
//________________________________________________________________________________________________________________________________________
 
struct FatEntry
{
u16 next_cluster; // the next cluster of the file.
} __attribute__((packed));
 
 
 
 
 
//________________________________________________________________________________________________________________________________________
//
// Partitions
//
//________________________________________________________________________________________________________________________________________
 
#define _EMPTY 0x00
#define _FAT12 0x01
#define _FAT16_ST_32_MB 0x04
#define _EXTENDED 0x05
#define _FAT16_LT_32_MB 0x06
#define _HPFS 0x07
#define _FAT32 0x0B
#define _FAT32_BIOS_Extension 0x0C
#define _FAT16_32_MB_BIOS_Extension 0x0E
#define _EXTENDED_BIOS_Extension 0x0F
#define _EISA 0x12
#define _DYNAMIC 0x42
#define _Linux_Swap 0x82
#define _Linux_Native 0x83
#define _Linux_LVM 0x8E
#define _FreeBSD 0xA5
#define _OpenBSD 0xA6
#define _NetBSD 0xA9
 
 
struct PartitionEntry
{
u8 PartitionState;
u8 BeginningHead;
u16 BeginningCylinder;
u8 Type;
u8 EndHead;
u16 EndCylinder;
u32 NoSectorsBeforePartition;
u32 NoSectorsPartition ;
} __attribute__((packed));
 
 
//________________________________________________________________________________________________________________________________________
//
// Structure of the VolumeBootRecord
//
//________________________________________________________________________________________________________________________________________
 
struct VBR_Entry
{
u8 dummy[11];
u16 bps;
u8 SectorsPerCluster;
u16 ReservedSectors;
u8 NoFATCopies;
u16 MaxRootEntries;
u16 dummy2;
u8 dummy3;
u16 SectorsPerFAT;
} __attribute__((packed));
 
 
 
//________________________________________________________________________________________________________________________________________
//
// Structure of the MasterBootRecord
//
//________________________________________________________________________________________________________________________________________
 
#define _MBR_SECTOR 0 // The MasterBootRecord is located in sector 0
 
struct MBR_Entry
{
u8 ExecutableCode[446];
struct PartitionEntry PartitionEntry1;
struct PartitionEntry PartitionEntry2;
struct PartitionEntry PartitionEntry3;
struct PartitionEntry PartitionEntry4;
u16 ExecutableMarker;
} __attribute__((packed));
 
 
 
 
//________________________________________________________________________________________________________________________________________
//
// API to the FAT16 filesystem
//
//________________________________________________________________________________________________________________________________________
 
extern u8 FAT16_Init(void);
extern File * fopen_(s8 *fname,s8 mode);
extern s16 fflush_(File *file);
extern void fclose_(File *file);
extern u32 fread_(void *buffer, u32 size, u32 count, File *file);
extern u32 fwrite_(void *buffer, u32 size, u32 count, File *file);
extern s16 fseek_(File *file, s32 offset, s16 origin);
extern s16 fgetchar_(File *file);
extern u8 fputchar_(File *file,s8 c);
extern u8 fputs_(File *file,s8 *string);
extern s8 * fgets_(s8 *s, s16 count, File *file);
extern s16 frename_(s8 *oldname, s8 *newname);
extern u8 fexist_(s8*fname);
extern u8 mkdir_(s8*fname);
extern u8 chdir_(s8 *fname);
extern u8 findfirst_(s8 *fname, Find *item, u8 attribute);
extern u8 findnext_(Find *item);
 
 
 
//________________________________________________________________________________________________________________________________________
//
// Functions needed internaly for the fat16 implementation
//
//________________________________________________________________________________________________________________________________________
 
extern u8 SeekFileInDirectory(s8*fname, File *file);
extern u8 CreateFileInDirectory(s8*fname, File *file);
extern u16 FindNextFreeCluster(File *file);
extern void SeperateFileName(s8*fname, s8*name);
extern u8 ScanSubDirectories(s8*fname, File *file);
extern u16 GetNextCluster(File *file);
extern u8 AppendCluster(File *file);
extern u16 GetFatClusterOffset(File *file);
extern u16 GetFatSectorIndex(File *file);
extern File * ReserveFilePointer(void);
extern u16 SeekSubDirectory(s8 *fname);
extern u8 CreateSubDirectory_(s8 *fname);
extern u8 FindItem(Find *);
extern void FreeFilePointer(File *file);
 
//________________________________________________________________________________________________________________________________________
//
// Vaiables needed internaly for the fat16 implementation
//
//________________________________________________________________________________________________________________________________________
 
extern u8 SectorsPerCluster;
extern u32 CWD;
 
 
 
#endif
 
 
 
 
/FollowMe/led.c
0,0 → 1,23
#include <inttypes.h>
#include "led.h"
 
 
// initializes the LED control outputs
void LED_Init(void)
{
#ifdef USE_SDLOGGER
// set PB0 as output (control of red LED)
DDRB |= (1<<DDB0);
LEDRED_OFF;
#endif
 
#ifdef USE_FOLLOWME
// set PB0 as output (control of yellow LED)
DDRB |= (1<<DDB0);
LEDYELLOW_OFF;
// set PB1 as output (control of red LED)
DDRB |= (1<<DDB1);
LEDRED_OFF;
#endif
 
}
/FollowMe/led.h
0,0 → 1,25
#ifndef _LED_H
#define _LED_H
 
#include <avr/io.h>
 
#ifdef USE_SDLOGGER
#define LEDRED_OFF PORTB |= (1<<PORTB0)
#define LEDRED_ON PORTB &= ~(1<<PORTB0)
#define LEDRED_TOGGLE PORTB ^= (1<<PORTB0)
#endif
 
#ifdef USE_FOLLOWME
#define LEDYELLOW_OFF PORTB |= (1<<PORTB0)
#define LEDYELLOW_ON PORTB &= ~(1<<PORTB0)
#define LEDYELLOW_TOGGLE PORTB ^= (1<<PORTB0)
 
#define LEDRED_OFF PORTB |= (1<<PORTB1)
#define LEDRED_ON PORTB &= ~(1<<PORTB1)
#define LEDRED_TOGGLE PORTB ^= (1<<PORTB1)
#endif
 
void LED_Init(void);
 
#endif //_LED_H
 
/FollowMe/main.c
0,0 → 1,115
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Copyright (c) 04.2007 Holger Buss
// + Nur für den privaten Gebrauch
// + www.MikroKopter.com
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Es gilt für das gesamte Projekt (Hardware, Software, Binärfiles, Sourcecode und Dokumentation),
// + dass eine Nutzung (auch auszugsweise) nur für den privaten und nicht-kommerziellen Gebrauch zulässig ist.
// + Sollten direkte oder indirekte kommerzielle Absichten verfolgt werden, ist mit uns (info@mikrokopter.de) Kontakt
// + bzgl. der Nutzungsbedingungen aufzunehmen.
// + Eine kommerzielle Nutzung ist z.B.Verkauf von MikroKoptern, Bestückung und Verkauf von Platinen oder Bausätzen,
// + Verkauf von Luftbildaufnahmen, usw.
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Werden Teile des Quellcodes (mit oder ohne Modifikation) weiterverwendet oder veröffentlicht,
// + unterliegen sie auch diesen Nutzungsbedingungen und diese Nutzungsbedingungen incl. Copyright müssen dann beiliegen
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Sollte die Software (auch auszugesweise) oder sonstige Informationen des MikroKopter-Projekts
// + auf anderen Webseiten oder Medien veröffentlicht werden, muss unsere Webseite "http://www.mikrokopter.de"
// + eindeutig als Ursprung verlinkt und genannt werden
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Keine Gewähr auf Fehlerfreiheit, Vollständigkeit oder Funktion
// + Benutzung auf eigene Gefahr
// + Wir übernehmen keinerlei Haftung für direkte oder indirekte Personen- oder Sachschäden
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Die Portierung der Software (oder Teile davon) auf andere Systeme (ausser der Hardware von www.mikrokopter.de) ist nur
// + mit unserer Zustimmung zulässig
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Die Funktion printf_P() unterliegt ihrer eigenen Lizenz und ist hiervon nicht betroffen
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Redistributions of source code (with or without modifications) must retain the above copyright notice,
// + this list of conditions and the following disclaimer.
// + * Neither the name of the copyright holders nor the names of contributors may be used to endorse or promote products derived
// + from this software without specific prior written permission.
// + * The use of this project (hardware, software, binary files, sources and documentation) is only permittet
// + for non-commercial use (directly or indirectly)
// + Commercial use (for 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 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 <avr/boot.h>
 
#include <avr/io.h>
#include <avr/interrupt.h>
 
#include "main.h"
#include "timer0.h"
#include "uart0.h"
#include "uart1.h"
#include "fat16.h"
#include "led.h"
#include "menu.h"
#include "printf_P.h"
 
int main (void)
{
// disable interrupts global
cli();
 
// disable watchdog
MCUSR &=~(1<<WDRF);
WDTCSR |= (1<<WDCE)|(1<<WDE);
WDTCSR = 0;
 
// initalize modules
LED_Init();
TIMER0_Init();
USART0_Init();
USART1_Init();
// enable interrupts global
sei();
 
#ifdef USE_SDLOGGER
printf("\n\rHW: SD-Logger");
#endif
#ifdef USE_FOLLOWME
printf("\n\rHW: Follow-Me");
#endif
printf("\n\rFollow Me\n\rSoftware:V%d.%d%c ",VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH + 'a');
printf("\n\r==============================");
printf("\n\r");
 
 
// try to initialize the SD-Card File system
printf("\n\rInit FAT16...");
if(FAT16_Init())
{
printf("ok");
}
else
{
printf("failed");
}
 
LCD_Clear();
 
while (1)
{
USART0_ProcessRxData();
USART0_TransmitTxData();
}
return (1);
}
 
/FollowMe/main.h
0,0 → 1,21
#ifndef _MAIN_H
#define _MAIN_H
 
#include <avr/io.h>
 
/*
#if defined (__AVR_ATmega644P__)
#define SYSCLK 20000000L //crystal freqency in Hz
#endif
*/
 
#define SYSCLK F_CPU
 
 
#endif //_MAIN_H
 
 
 
 
 
 
/FollowMe/makefile
0,0 → 1,430
#--------------------------------------------------------------------
# MCU name
MCU = atmega644p
F_CPU = 20000000
#-------------------------------------------------------------------
VERSION_MAJOR = 0
VERSION_MINOR = 1
VERSION_PATCH = 0
 
VERSION_SERIAL_MAJOR = 10 # Serial Protocol Major Version
VERSION_SERIAL_MINOR = 0 # Serial Protocol Minor Version
 
#-------------------------------------------------------------------
#OPTIONS
# Use one of the motor setups
#BOARD = FOLLOWME
BOARD = SDLOGGER
 
#-------------------------------------------------------------------
# get SVN revision
REV := $(shell sh -c "cat .svn/entries | sed -n '4p'")
 
ifeq ($(MCU), atmega644p)
FUSE_SETTINGS = -u -U lfuse:w:0xff:m -U hfuse:w:0xdf:m
HEX_NAME = MEGA644p_$(BOARD)
endif
 
ifeq ($(F_CPU), 20000000)
QUARZ = 20MHZ
endif
 
 
# Output format. (can be srec, ihex, binary)
FORMAT = ihex
 
# Target file name (without extension).
 
ifeq ($(VERSION_PATCH), 0)
TARGET = FollowMe_$(HEX_NAME)_V$(VERSION_MAJOR)_$(VERSION_MINOR)a_SVN$(REV)
endif
ifeq ($(VERSION_PATCH), 1)
TARGET = FollowMe_$(HEX_NAME)_V$(VERSION_MAJOR)_$(VERSION_MINOR)b_SVN$(REV)
endif
ifeq ($(VERSION_PATCH), 2)
TARGET = FollowMe_$(HEX_NAME)_V$(VERSION_MAJOR)_$(VERSION_MINOR)c_SVN$(REV)
endif
ifeq ($(VERSION_PATCH), 3)
TARGET = FollowMe_$(HEX_NAME)_V$(VERSION_MAJOR)_$(VERSION_MINOR)d_SVN$(REV)
endif
ifeq ($(VERSION_PATCH), 4)
TARGET = FollowMe_$(HEX_NAME)_V$(VERSION_MAJOR)_$(VERSION_MINOR)e_SVN$(REV)
endif
ifeq ($(VERSION_PATCH), 5)
TARGET = FollowMe_$(HEX_NAME)_V$(VERSION_MAJOR)_$(VERSION_MINOR)f_SVN$(REV)
endif
ifeq ($(VERSION_PATCH), 6)
TARGET = FollowMe_$(HEX_NAME)_V$(VERSION_MAJOR)_$(VERSION_MINOR)g_SVN$(REV)
endif
ifeq ($(VERSION_PATCH), 7)
TARGET = FollowMe_$(HEX_NAME)_V$(VERSION_MAJOR)_$(VERSION_MINOR)h_SVN$(REV)
endif
ifeq ($(VERSION_PATCH), 8)
TARGET = FollowMe_$(HEX_NAME)_V$(VERSION_MAJOR)_$(VERSION_MINOR)i_SVN$(REV)
endif
ifeq ($(VERSION_PATCH), 9)
TARGET = FollowMe_$(HEX_NAME)_V$(VERSION_MAJOR)_$(VERSION_MINOR)j_SVN$(REV)
endif
ifeq ($(VERSION_PATCH), 10)
TARGET = FollowMe_$(HEX_NAME)_V$(VERSION_MAJOR)_$(VERSION_MINOR)k_SVN$(REV)
endif
 
 
# Optimization level, can be [0, 1, 2, 3, s]. 0 turns off optimization.
# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
OPT = s
 
##########################################################################################################
# List C source files here. (C dependencies are automatically generated.)
SRC = main.c uart0.c uart1.c printf_P.c timer0.c menu.c led.c ubx.c ssc.c sdc.c fat16.c
 
##########################################################################################################
 
 
# List Assembler source files here.
# Make them always end in a capital .S. Files ending in a lowercase .s
# will not be considered source files but generated files (assembler
# output from the compiler), and will be deleted upon "make clean"!
# Even though the DOS/Win* filesystem matches both .s and .S the same,
# it will preserve the spelling of the filenames, and gcc itself does
# care about how the name is spelled on its command-line.
ASRC =
 
 
 
# List any extra directories to look for include files here.
# Each directory must be seperated by a space.
EXTRAINCDIRS =
 
 
# Optional compiler flags.
# -g: generate debugging information (for GDB, or for COFF conversion)
# -O*: optimization level
# -f...: tuning, see gcc manual and avr-libc documentation
# -Wall...: warning level
# -Wa,...: tell GCC to pass this to the assembler.
# -ahlms: create assembler listing
CFLAGS = -O$(OPT) \
-funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums \
-Wall -Wstrict-prototypes \
-Wa,-adhlns=$(<:.c=.lst) \
$(patsubst %,-I%,$(EXTRAINCDIRS))
 
 
# Set a "language standard" compiler flag.
# Unremark just one line below to set the language standard to use.
# gnu99 = C99 + GNU extensions. See GCC manual for more information.
#CFLAGS += -std=c89
#CFLAGS += -std=gnu89
#CFLAGS += -std=c99
CFLAGS += -std=gnu99
 
CFLAGS += -DF_CPU=$(F_CPU) -DVERSION_MAJOR=$(VERSION_MAJOR) -DVERSION_MINOR=$(VERSION_MINOR) -DVERSION_PATCH=$(VERSION_PATCH) -DVERSION_SERIAL_MAJOR=$(VERSION_SERIAL_MAJOR) -DVERSION_SERIAL_MINOR=$(VERSION_SERIAL_MINOR)
 
ifeq ($(BOARD), FOLLOWME)
CFLAGS += -DUSE_FOLLOWME
endif
ifeq ($(BOARD), SDLOGGER)
CFLAGS += -DUSE_SDLOGGER
endif
 
 
# Optional assembler flags.
# -Wa,...: tell GCC to pass this to the assembler.
# -ahlms: create listing
# -gstabs: have the assembler create line number information; note that
# for use in COFF files, additional information about filenames
# and function names needs to be present in the assembler source
# files -- see avr-libc docs [FIXME: not yet described there]
ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs
 
 
 
# Optional linker flags.
# -Wl,...: tell GCC to pass this to linker.
# -Map: create map file
# --cref: add cross reference to map file
LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
 
# Additional libraries
 
# Minimalistic printf version
#LDFLAGS += -Wl,-u,vfprintf -lprintf_min
 
# Floating point printf version (requires -lm below)
#LDFLAGS += -Wl,-u,vfprintf -lprintf_flt
 
# -lm = math library
LDFLAGS += -lm
 
 
##LDFLAGS += -T./linkerfile/avr5.x
 
 
 
# Programming support using avrdude. Settings and variables.
 
# Programming hardware: alf avr910 avrisp bascom bsd
# dt006 pavr picoweb pony-stk200 sp12 stk200 stk500
#
# Type: avrdude -c ?
# to get a full listing.
#
#AVRDUDE_PROGRAMMER = dt006
#AVRDUDE_PROGRAMMER = stk200
#AVRDUDE_PROGRAMMER = ponyser
AVRDUDE_PROGRAMMER = avrispv2
#falls Ponyser ausgewählt wird, muss sich unsere avrdude-Configdatei im Bin-Verzeichnis des Compilers befinden
 
#AVRDUDE_PORT = com1 # programmer connected to serial device
#AVRDUDE_PORT = lpt1 # programmer connected to parallel port
AVRDUDE_PORT = usb # programmer connected to USB
 
#AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex
AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex $(FUSE_SETTINGS)
#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep
 
#avrdude -c avrispv2 -P usb -p m32 -U flash:w:blink.hex
AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
 
# Uncomment the following if you want avrdude's erase cycle counter.
# Note that this counter needs to be initialized first using -Yn,
# see avrdude manual.
#AVRDUDE_ERASE += -y
 
# Uncomment the following if you do /not/ wish a verification to be
# performed after programming the device.
AVRDUDE_FLAGS += -V
 
# Increase verbosity level. Please use this when submitting bug
# reports about avrdude. See <http://savannah.nongnu.org/projects/avrdude>
# to submit bug reports.
#AVRDUDE_FLAGS += -v -v
 
# ---------------------------------------------------------------------------
# Define directories, if needed.
DIRAVR = c:/winavr
DIRAVRBIN = $(DIRAVR)/bin
DIRAVRUTILS = $(DIRAVR)/utils/bin
DIRINC = .
DIRLIB = $(DIRAVR)/avr/lib
 
 
# Define programs and commands.
SHELL = sh
 
CC = avr-gcc
 
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
SIZE = avr-size
 
# Programming support using avrdude.
AVRDUDE = avrdude
 
REMOVE = rm -f
COPY = cp
 
HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
ELFSIZE = $(SIZE) -A $(TARGET).elf
 
# Define Messages
# English
MSG_ERRORS_NONE = Errors: none
MSG_BEGIN = -------- begin --------
MSG_END = -------- end --------
MSG_SIZE_BEFORE = Size before:
MSG_SIZE_AFTER = Size after:
MSG_COFF = Converting to AVR COFF:
MSG_EXTENDED_COFF = Converting to AVR Extended COFF:
MSG_FLASH = Creating load file for Flash:
MSG_EEPROM = Creating load file for EEPROM:
MSG_EXTENDED_LISTING = Creating Extended Listing:
MSG_SYMBOL_TABLE = Creating Symbol Table:
MSG_LINKING = Linking:
MSG_COMPILING = Compiling:
MSG_ASSEMBLING = Assembling:
MSG_CLEANING = Cleaning project:
 
 
# Define all object files.
OBJ = $(SRC:.c=.o) $(ASRC:.S=.o)
 
# Define all listing files.
LST = $(ASRC:.S=.lst) $(SRC:.c=.lst)
 
# Combine all necessary flags and optional flags.
# Add target processor to flags.
#ALL_CFLAGS = -mmcu=$(MCU) -DF_CPU=$(F_CPU) -I. $(CFLAGS)
ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS)
ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
 
 
# Default target.
all: begin gccversion sizebefore $(TARGET).elf $(TARGET).hex $(TARGET).eep \
$(TARGET).lss $(TARGET).sym sizeafter finished end
 
 
# Eye candy.
# AVR Studio 3.x does not check make's exit code but relies on
# the following magic strings to be generated by the compile job.
begin:
@echo
@echo $(MSG_BEGIN)
 
finished:
@echo $(MSG_ERRORS_NONE)
 
end:
@echo $(MSG_END)
@echo
 
 
# Display size of file.
sizebefore:
@if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); echo; fi
 
sizeafter:
@if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); echo; fi
 
 
 
# Display compiler version information.
gccversion :
@$(CC) --version
 
 
# Convert ELF to COFF for use in debugging / simulating in
# AVR Studio or VMLAB.
COFFCONVERT=$(OBJCOPY) --debugging \
--change-section-address .data-0x800000 \
--change-section-address .bss-0x800000 \
--change-section-address .noinit-0x800000 \
--change-section-address .eeprom-0x810000
 
 
coff: $(TARGET).elf
@echo
@echo $(MSG_COFF) $(TARGET).cof
$(COFFCONVERT) -O coff-avr $< $(TARGET).cof
 
 
extcoff: $(TARGET).elf
@echo
@echo $(MSG_EXTENDED_COFF) $(TARGET).cof
$(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof
 
 
 
 
# Program the device.
program: $(TARGET).hex $(TARGET).eep
$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)
 
 
 
 
# Create final output files (.hex, .eep) from ELF output file.
%.hex: %.elf
@echo
@echo $(MSG_FLASH) $@
$(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
 
%.eep: %.elf
@echo
@echo $(MSG_EEPROM) $@
-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
--change-section-lma .eeprom=0 -O $(FORMAT) $< $@
 
# Create extended listing file from ELF output file.
%.lss: %.elf
@echo
@echo $(MSG_EXTENDED_LISTING) $@
$(OBJDUMP) -h -S $< > $@
 
# Create a symbol table from ELF output file.
%.sym: %.elf
@echo
@echo $(MSG_SYMBOL_TABLE) $@
avr-nm -n $< > $@
 
 
 
# Link: create ELF output file from object files.
.SECONDARY : $(TARGET).elf
.PRECIOUS : $(OBJ)
%.elf: $(OBJ)
@echo
@echo $(MSG_LINKING) $@
$(CC) $(ALL_CFLAGS) $(OBJ) --output $@ $(LDFLAGS)
 
 
# Compile: create object files from C source files.
%.o : %.c
@echo
@echo $(MSG_COMPILING) $<
$(CC) -c $(ALL_CFLAGS) $< -o $@
 
 
# Compile: create assembler files from C source files.
%.s : %.c
$(CC) -S $(ALL_CFLAGS) $< -o $@
 
 
# Assemble: create object files from assembler source files.
%.o : %.S
@echo
@echo $(MSG_ASSEMBLING) $<
$(CC) -c $(ALL_ASFLAGS) $< -o $@
 
 
 
 
 
 
# Target: clean project.
clean: begin clean_list finished end
 
clean_list :
@echo
@echo $(MSG_CLEANING)
# $(REMOVE) $(TARGET).hex
$(REMOVE) $(TARGET).eep
$(REMOVE) $(TARGET).obj
$(REMOVE) $(TARGET).cof
$(REMOVE) $(TARGET).elf
$(REMOVE) $(TARGET).map
$(REMOVE) $(TARGET).obj
$(REMOVE) $(TARGET).a90
$(REMOVE) $(TARGET).sym
$(REMOVE) $(TARGET).lnk
$(REMOVE) $(TARGET).lss
$(REMOVE) $(OBJ)
$(REMOVE) $(LST)
$(REMOVE) $(SRC:.c=.s)
$(REMOVE) $(SRC:.c=.d)
 
 
# Automatically generate C source code dependencies.
# (Code originally taken from the GNU make user manual and modified
# (See README.txt Credits).)
#
# Note that this will work with sh (bash) and sed that is shipped with WinAVR
# (see the SHELL variable defined above).
# This may not work with other shells or other seds.
#
%.d: %.c
set -e; $(CC) -MM $(ALL_CFLAGS) $< \
| sed 's,\(.*\)\.o[ :]*,\1.o \1.d : ,g' > $@; \
[ -s $@ ] || rm -f $@
 
 
# Remove the '-' if you want to see the dependency files generated.
-include $(SRC:.c=.d)
 
 
 
# Listing of phony targets.
.PHONY : all begin finish end sizebefore sizeafter gccversion coff extcoff \
clean clean_list program
 
/FollowMe/menu.c
0,0 → 1,129
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Copyright (c) 04.2007 Holger Buss
// + only for non-profit use
// + www.MikroKopter.com
// + see the File "License.txt" for further Informations
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
#include <stdlib.h>
#include <inttypes.h>
#include "main.h"
#include "uart0.h"
#include "printf_P.h"
#include "ubx.h"
 
uint8_t MaxMenuItem = 1;
uint8_t MenuItem = 0;
uint8_t RemoteKeys = 0;
 
#define KEY1 0x01
#define KEY2 0x02
#define KEY3 0x04
#define KEY4 0x08
#define KEY5 0x10
 
 
 
#define DISPLAYBUFFSIZE 80
int8_t DisplayBuff[DISPLAYBUFFSIZE] = "Hello World";
uint8_t DispPtr = 0;
 
 
/************************************/
/* Clear LCD Buffer */
/************************************/
void LCD_Clear(void)
{
uint8_t i;
for( i = 0; i < DISPLAYBUFFSIZE; i++) DisplayBuff[i] = ' ';
}
 
 
/************************************/
/* Update Menu on LCD */
/************************************/
// Display with 20 characters in 4 lines
void LCD_PrintMenu(void)
{
if(RemoteKeys & KEY1)
{
if(MenuItem) MenuItem--;
else MenuItem = MaxMenuItem;
}
if(RemoteKeys & KEY2)
{
if(MenuItem == MaxMenuItem) MenuItem = 0;
else MenuItem++;
}
if((RemoteKeys & KEY1) && (RemoteKeys & KEY2)) MenuItem = 0;
 
LCD_Clear();
 
if(MenuItem > MaxMenuItem) MenuItem = MaxMenuItem;
// print menu item number in the upper right corner
if(MenuItem < 10)
{
LCD_printfxy(17,0,"[%i]",MenuItem);
}
else
{
LCD_printfxy(16,0,"[%i]",MenuItem);
}
 
switch(MenuItem)
{
case 0:// Version Info Menu Item
LCD_printfxy(0,0,"+ Follow Me +");
#ifdef USE_SDLOGGER
LCD_printfxy(0,1,"HW: SD-Logger");
#endif
#ifdef USE_FOLLOWME
LCD_printfxy(0,1,"HW: Follow-Me");
#endif
LCD_printfxy(0,2,"SW: %d.%d%c", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH+'a');
LCD_printfxy(0,3," ");
break;
 
case 1://GPS Lat/Lon coords
if (GPSInfo.status == INVALID)
{
LCD_printfxy(0,0,"No GPS data!");
}
else
{
switch (GPSInfo.satfix)
{
case SATFIX_NONE:
LCD_printfxy(0,0,"Sats: %d Fix: No", GPSInfo.satnum);
break;
case SATFIX_2D:
LCD_printfxy(0,0,"Sats: %d Fix: 2D", GPSInfo.satnum);
break;
case SATFIX_3D:
LCD_printfxy(0,0,"Sats: %d Fix: 3D", GPSInfo.satnum);
break;
default:
LCD_printfxy(0,0,"Sats: %d Fix: ??", GPSInfo.satnum);
break;
}
int16_t i1,i2,i3;
i1 = (int16_t)(GPSInfo.longitude/10000000L);
i2 = abs((int16_t)((GPSInfo.longitude%10000000L)/10000L));
i3 = abs((int16_t)(((GPSInfo.longitude%10000000L)%10000L)/10L));
LCD_printfxy(0,1,"Lon: %d.%.3d%.3d deg",i1, i2, i3);
i1 = (int16_t)(GPSInfo.latitude/10000000L);
i2 = abs((int16_t)((GPSInfo.latitude%10000000L)/10000L));
i3 = abs((int16_t)(((GPSInfo.latitude%10000000L)%10000L)/10L));
LCD_printfxy(0,2,"Lat: %d.%.3d%.3d deg",i1, i2, i3);
i1 = (int16_t)(GPSInfo.altitude/1000L);
i2 = abs((int16_t)(GPSInfo.altitude%1000L));
LCD_printfxy(0,3,"Alt: %d.%.3d m",i1, i2);
}
break;
 
default: MaxMenuItem = MenuItem - 1;
MenuItem = 0;
break;
}
RemoteKeys = 0;
}
/FollowMe/menu.h
0,0 → 1,17
#ifndef _MENU_H
#define _MENU_H
 
#include <inttypes.h>
 
#define DISPLAYBUFFSIZE 80
 
extern void LCD_PrintMenu(void);
extern void LCD_Clear(void);
extern int8_t DisplayBuff[DISPLAYBUFFSIZE];
extern uint8_t DispPtr;
extern uint8_t MenuItem;
extern uint8_t MaxMenuItem;
extern uint8_t RemoteKeys;
#endif //_MENU_H
 
 
/FollowMe/old_macros.h
0,0 → 1,47
/*
For backwards compatibility only.
Ingo Busker ingo@mikrocontroller.com
*/
 
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
 
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
 
#ifndef inb
#define inb(sfr) _SFR_BYTE(sfr)
#endif
 
#ifndef outb
#define outb(sfr, val) (_SFR_BYTE(sfr) = (val))
#endif
 
#ifndef inw
#define inw(sfr) _SFR_WORD(sfr)
#endif
 
#ifndef outw
#define outw(sfr, val) (_SFR_WORD(sfr) = (val))
#endif
 
#ifndef outp
#define outp(val, sfr) outb(sfr, val)
#endif
 
#ifndef inp
#define inp(sfr) inb(sfr)
#endif
 
#ifndef BV
#define BV(bit) _BV(bit)
#endif
 
 
#ifndef PRG_RDB
#define PRG_RDB pgm_read_byte
#endif
 
/FollowMe/printf_P.c
0,0 → 1,483
// Die Funktion printf_P() unterliegt ihrer eigenen Lizenz und ist nicht von der Lizenz für den MikroKopter-Teil unterstellt
 
/*
Copyright (C) 1993 Free Software Foundation
 
This file is part of the GNU IO Library. This library is free
software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option)
any later version.
 
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this library; see the file COPYING. If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
As a special exception, if you link this library with files
compiled with a GNU compiler to produce an executable, this does not cause
the resulting executable to be covered by the GNU General Public License.
This exception does not however invalidate any other reasons why
the executable file might be covered by the GNU General Public License. */
 
/*
* Copyright (c) 1990 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. [rescinded 22 July 1999]
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
 
/******************************************************************************
This file is a patched version of printf called _printf_P
It is made to work with avr-gcc for Atmel AVR MCUs.
There are some differences from standard printf:
1. There is no floating point support (with fp the code is about 8K!)
2. Return type is void
3. Format string must be in program memory (by using macro printf this is
done automaticaly)
4. %n is not implemented (just remove the comment around it if you need it)
5. If LIGHTPRINTF is defined, the code is about 550 bytes smaller and the
folowing specifiers are disabled :
space # * . - + p s o O
6. A function void uart_sendchar(char c) is used for output. The UART must
be initialized before using printf.
 
Alexander Popov
sasho@vip.orbitel.bg
******************************************************************************/
 
/*
* Actual printf innards.
*
* This code is large and complicated...
*/
 
#include <string.h>
#ifdef __STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif
 
#include "old_macros.h"
#include "printf_P.h"
#include "menu.h"
#include "uart0.h"
 
 
//#define LIGHTPRINTF
char PrintZiel;
 
 
char Putchar(char zeichen)
{
if(PrintZiel == OUT_LCD) { DisplayBuff[DispPtr++] = zeichen; return(1);}
else return(uart_putchar(zeichen));
}
 
 
void PRINT(const char * ptr, unsigned int len)
{
for(;len;len--) Putchar(*ptr++);
}
 
void PRINTP(const char * ptr, unsigned int len)
{
for(;len;len--) Putchar(pgm_read_byte(ptr++));
}
 
void PAD_SP(signed char howmany)
{
for(;howmany>0;howmany--) Putchar(' ');
}
 
void PAD_0(signed char howmany)
{
for(;howmany>0;howmany--) Putchar('0');
}
 
#define BUF 40
 
/*
* Macros for converting digits to letters and vice versa
*/
#define to_digit(c) ((c) - '0')
#define is_digit(c) ((c)<='9' && (c)>='0')
#define to_char(n) ((n) + '0')
 
/*
* Flags used during conversion.
*/
#define LONGINT 0x01 /* long integer */
#define LONGDBL 0x02 /* long double; unimplemented */
#define SHORTINT 0x04 /* short integer */
#define ALT 0x08 /* alternate form */
#define LADJUST 0x10 /* left adjustment */
#define ZEROPAD 0x20 /* zero (as opposed to blank) pad */
#define HEXPREFIX 0x40 /* add 0x or 0X prefix */
 
void _printf_P (char ziel,char const *fmt0, ...) /* Works with string from FLASH */
{
va_list ap;
register const char *fmt; /* format string */
register char ch; /* character from fmt */
register int n; /* handy integer (short term usage) */
register char *cp; /* handy char pointer (short term usage) */
const char *fmark; /* for remembering a place in fmt */
register unsigned char flags; /* flags as above */
signed char width; /* width from format (%8d), or 0 */
signed char prec; /* precision from format (%.3d), or -1 */
char sign; /* sign prefix (' ', '+', '-', or \0) */
unsigned long _ulong=0; /* integer arguments %[diouxX] */
#define OCT 8
#define DEC 10
#define HEX 16
unsigned char base; /* base for [diouxX] conversion */
signed char dprec; /* a copy of prec if [diouxX], 0 otherwise */
signed char dpad; /* extra 0 padding needed for integers */
signed char fieldsz; /* field size expanded by sign, dpad etc */
/* The initialization of 'size' is to suppress a warning that
'size' might be used unitialized. It seems gcc can't
quite grok this spaghetti code ... */
signed char size = 0; /* size of converted field or string */
char buf[BUF]; /* space for %c, %[diouxX], %[eEfgG] */
char ox[2]; /* space for 0x hex-prefix */
 
PrintZiel = ziel; // bestimmt, LCD oder UART
va_start(ap, fmt0);
 
fmt = fmt0;
 
/*
* Scan the format for conversions (`%' character).
*/
for (;;) {
for (fmark = fmt; (ch = pgm_read_byte(fmt)) != '\0' && ch != '%'; fmt++)
/* void */;
if ((n = fmt - fmark) != 0) {
PRINTP(fmark, n);
}
if (ch == '\0')
goto done;
fmt++; /* skip over '%' */
 
flags = 0;
dprec = 0;
width = 0;
prec = -1;
sign = '\0';
 
rflag: ch = PRG_RDB(fmt++);
reswitch:
#ifdef LIGHTPRINTF
if (ch=='o' || ch=='u' || (ch|0x20)=='x') {
#else
if (ch=='u' || (ch|0x20)=='x') {
#endif
if (flags&LONGINT) {
_ulong=va_arg(ap, unsigned long);
} else {
register unsigned int _d;
_d=va_arg(ap, unsigned int);
_ulong = flags&SHORTINT ? (unsigned long)(unsigned short)_d : (unsigned long)_d;
}
}
 
#ifndef LIGHTPRINTF
if(ch==' ') {
/*
* ``If the space and + flags both appear, the space
* flag will be ignored.''
* -- ANSI X3J11
*/
if (!sign)
sign = ' ';
goto rflag;
} else if (ch=='#') {
flags |= ALT;
goto rflag;
} else if (ch=='*'||ch=='-') {
if (ch=='*') {
/*
* ``A negative field width argument is taken as a
* - flag followed by a positive field width.''
* -- ANSI X3J11
* They don't exclude field widths read from args.
*/
if ((width = va_arg(ap, int)) >= 0)
goto rflag;
width = -width;
}
flags |= LADJUST;
flags &= ~ZEROPAD; /* '-' disables '0' */
goto rflag;
} else if (ch=='+') {
sign = '+';
goto rflag;
} else if (ch=='.') {
if ((ch = PRG_RDB(fmt++)) == '*') {
n = va_arg(ap, int);
prec = n < 0 ? -1 : n;
goto rflag;
}
n = 0;
while (is_digit(ch)) {
n = n*10 + to_digit(ch);
ch = PRG_RDB(fmt++);
}
prec = n < 0 ? -1 : n;
goto reswitch;
} else
#endif /* LIGHTPRINTF */
if (ch=='0') {
/*
* ``Note that 0 is taken as a flag, not as the
* beginning of a field width.''
* -- ANSI X3J11
*/
if (!(flags & LADJUST))
flags |= ZEROPAD; /* '-' disables '0' */
goto rflag;
} else if (ch>='1' && ch<='9') {
n = 0;
do {
n = 10 * n + to_digit(ch);
ch = PRG_RDB(fmt++);
} while (is_digit(ch));
width = n;
goto reswitch;
} else if (ch=='h') {
flags |= SHORTINT;
goto rflag;
} else if (ch=='l') {
flags |= LONGINT;
goto rflag;
} else if (ch=='c') {
*(cp = buf) = va_arg(ap, int);
size = 1;
sign = '\0';
} else if (ch=='D'||ch=='d'||ch=='i') {
if(ch=='D')
flags |= LONGINT;
if (flags&LONGINT) {
_ulong=va_arg(ap, long);
} else {
register int _d;
_d=va_arg(ap, int);
_ulong = flags&SHORTINT ? (long)(short)_d : (long)_d;
}
 
if ((long)_ulong < 0) {
_ulong = -_ulong;
sign = '-';
}
base = DEC;
goto number;
} else
/*
if (ch=='n') {
if (flags & LONGINT)
*va_arg(ap, long *) = ret;
else if (flags & SHORTINT)
*va_arg(ap, short *) = ret;
else
*va_arg(ap, int *) = ret;
continue; // no output
} else
*/
#ifndef LIGHTPRINTF
if (ch=='O'||ch=='o') {
if (ch=='O')
flags |= LONGINT;
base = OCT;
goto nosign;
} else if (ch=='p') {
/*
* ``The argument shall be a pointer to void. The
* value of the pointer is converted to a sequence
* of printable characters, in an implementation-
* defined manner.''
* -- ANSI X3J11
*/
/* NOSTRICT */
_ulong = (unsigned int)va_arg(ap, void *);
base = HEX;
flags |= HEXPREFIX;
ch = 'x';
goto nosign;
} else if (ch=='s') { // print a string from RAM
if ((cp = va_arg(ap, char *)) == NULL) {
cp=buf;
cp[0] = '(';
cp[1] = 'n';
cp[2] = 'u';
cp[4] = cp[3] = 'l';
cp[5] = ')';
cp[6] = '\0';
}
if (prec >= 0) {
/*
* can't use strlen; can only look for the
* NUL in the first `prec' characters, and
* strlen() will go further.
*/
char *p = (char*)memchr(cp, 0, prec);
 
if (p != NULL) {
size = p - cp;
if (size > prec)
size = prec;
} else
size = prec;
} else
size = strlen(cp);
sign = '\0';
} else
#endif /* LIGHTPRINTF */
if(ch=='U'||ch=='u') {
if (ch=='U')
flags |= LONGINT;
base = DEC;
goto nosign;
} else if (ch=='X'||ch=='x') {
base = HEX;
/* leading 0x/X only if non-zero */
if (flags & ALT && _ulong != 0)
flags |= HEXPREFIX;
 
/* unsigned conversions */
nosign: sign = '\0';
/*
* ``... diouXx conversions ... if a precision is
* specified, the 0 flag will be ignored.''
* -- ANSI X3J11
*/
number: if ((dprec = prec) >= 0)
flags &= ~ZEROPAD;
 
/*
* ``The result of converting a zero value with an
* explicit precision of zero is no characters.''
* -- ANSI X3J11
*/
cp = buf + BUF;
if (_ulong != 0 || prec != 0) {
register unsigned char _d,notlastdigit;
do {
notlastdigit=(_ulong>=base);
_d = _ulong % base;
 
if (_d<10) {
_d+='0';
} else {
_d+='a'-10;
if (ch=='X') _d&=~0x20;
}
*--cp=_d;
_ulong /= base;
} while (notlastdigit);
#ifndef LIGHTPRINTF
// handle octal leading 0
if (base==OCT && flags & ALT && *cp != '0')
*--cp = '0';
#endif
}
 
size = buf + BUF - cp;
} else { //default
/* "%?" prints ?, unless ? is NUL */
if (ch == '\0')
goto done;
/* pretend it was %c with argument ch */
cp = buf;
*cp = ch;
size = 1;
sign = '\0';
}
 
/*
* All reasonable formats wind up here. At this point,
* `cp' points to a string which (if not flags&LADJUST)
* should be padded out to `width' places. If
* flags&ZEROPAD, it should first be prefixed by any
* sign or other prefix; otherwise, it should be blank
* padded before the prefix is emitted. After any
* left-hand padding and prefixing, emit zeroes
* required by a decimal [diouxX] precision, then print
* the string proper, then emit zeroes required by any
* leftover floating precision; finally, if LADJUST,
* pad with blanks.
*/
 
/*
* compute actual size, so we know how much to pad.
*/
fieldsz = size;
 
dpad = dprec - size;
if (dpad < 0)
dpad = 0;
 
if (sign)
fieldsz++;
else if (flags & HEXPREFIX)
fieldsz += 2;
fieldsz += dpad;
 
/* right-adjusting blank padding */
if ((flags & (LADJUST|ZEROPAD)) == 0)
PAD_SP(width - fieldsz);
 
/* prefix */
if (sign) {
PRINT(&sign, 1);
} else if (flags & HEXPREFIX) {
ox[0] = '0';
ox[1] = ch;
PRINT(ox, 2);
}
 
/* right-adjusting zero padding */
if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
PAD_0(width - fieldsz);
 
/* leading zeroes from decimal precision */
PAD_0(dpad);
 
/* the string or number proper */
PRINT(cp, size);
 
/* left-adjusting padding (always blank) */
if (flags & LADJUST)
PAD_SP(width - fieldsz);
}
done:
va_end(ap);
}
/FollowMe/printf_P.h
0,0 → 1,19
#ifndef _PRINTF_P_H_
#define _PRINTF_P_H_
 
#include <avr/pgmspace.h>
 
#define OUT_V24 0
#define OUT_LCD 1
 
 
void _printf_P (char, char const *fmt0, ...);
extern char PrintZiel;
 
 
#define printf_P(format, args...) _printf_P(OUT_V24,format , ## args)
#define printf(format, args...) _printf_P(OUT_V24,PSTR(format) , ## args)
#define LCD_printfxy(x,y,format, args...) { DispPtr = y * 20 + x; _printf_P(OUT_LCD,PSTR(format) , ## args);}
#define LCD_printf(format, args...) { _printf_P(OUT_LCD,PSTR(format) , ## args);}
 
#endif
/FollowMe/sdc.c
0,0 → 1,254
#include <avr/io.h>
#include <util/delay.h>
#include "fat16.h"
#include "sdc.h"
#include "ssc.h"
 
//________________________________________________________________________________________________________________________________________
// Module name: mmc.c
// Compiler used: avr-gcc 3.4.5
// Last Modifikation: 24.07.2007
// Version: 1.05
// Authors: Stephan Busker
// Description: Source files for connecting to an sdcard using the SSC
//
//........................................................................................................................................
// Functions: u8 SDC_init(void);
// u8 SDC_PutCommand (u8*CMD);
// u8 SDC_PutSector(u32 addr,u8*Buffer);
// u8 SDC_GetSector(u32 addr,u8*Buffer);
// void SDC_GetBlock(u8*CMD,u8*Buffer,u16 Bytes);
//
////........................................................................................................................................
// ext. functions: extern void SSC_Init(void);
// extern u8 SSC_GetChar (void);
// extern void SSC_PutChar (u8);
// extern void SSC_Enable(void);
// extern void SSC_Disable(void);
//........................................................................................................................................
//
// URL: www.Mikro-Control.de
// mailto: stephan.busker@mikro-control.de
//________________________________________________________________________________________________________________________________________
 
 
 
 
//________________________________________________________________________________________________________________________________________
// Funtion: SDC_Init(void);
//
// Description: This function initialises the SDCard to spi-mode.
//
//
// Returnvalue: the function returns 0 if the initialisation was successfull otherwise the function returns an errorcode.
//________________________________________________________________________________________________________________________________________
 
u8 SDC_Init(void)
{
u8 Timeout = 0;
u8 CMD[] = {0x40,0x00,0x00,0x00,0x00,0x95};
u16 a = 0;
u8 b = 0;
 
SSC_Init(); // Initialise SSC to transmit data to the sdcard.
 
 
_delay_ms(10); // before initialising the sdcard wait for 10ms
 
 
for (b=0;b<0x0f;b++) // sending 74Clocks brings the sdcard into spimode.
{
_delay_us(1); // wait at least 1us between the characters.
SSC_PutChar(0xff);
}
while(SDC_PutCommand (CMD) !=1) // Sending CMD0 (Reset) to the sdcard.
{
if (Timeout++ > 200)
{
return(1);
}
}
Timeout = 0;
CMD[0] = 0x41;
CMD[5] = 0xFF;
while( SDC_PutCommand (CMD) !=0) // Sending CMD1 to the sdcard.
{
if (Timeout++ > 100)
{
return(2);
}
}
 
SSC_Disable(); // disable sdcard.
return(0);
}
 
 
 
 
//________________________________________________________________________________________________________________________________________
// Funtion: SDC_PutCommand(* CMD);
//
// Description: This function initialises the SDCard to spi-mode.
//
//
// Returnvalue: the function returns 0 if the initialisation was successfull otherwise the function returns an errorcode.
//________________________________________________________________________________________________________________________________________
 
u8 SDC_PutCommand (u8*CMD)
{
u8 tmp = 0xff;
u8 Timeout = 0;
u16 a = 0;
 
 
#ifdef SSC_RX_FIFO
SSC_ClearRxFifo();
#endif
SSC_Disable(); // disable chipselect
SSC_PutChar(0xFF); // Send 8 Clocks to the sdcard while card is not selected.
SSC_Enable(); // enable chipselect.
 
if (*CMD == 0x41) _delay_ms(10); // if command is CMD0 generate a short delay.
for (a = 0;a<0x06;a++) // send the command sequence to the sdcard (6 bytes)
{
SSC_PutChar(*CMD++);
}
 
#ifdef SSC_RX_FIFO
SSC_ClearRxFifo();
#endif
while (tmp == 0xff) // Wait for response from sdcard.
{
tmp = SSC_GetChar();
if (Timeout++ > 100)
{
break; // or timeout.
}
}
 
return(tmp);
}
 
 
 
 
//________________________________________________________________________________________________________________________________________
// Funtion: SDC_PutSector(void);
//
// Description: This function writes one sector of data to the SSC
//
//
// Returnvalue: none
//________________________________________________________________________________________________________________________________________
 
u8 SDC_PutSector(u32 addr,u8*Buffer)
{
u8 tmp;
u8 CMD[] = {0x58,0x00,0x00,0x00,0x00,0xFF};
addr = addr << 9; // convert sectoradress to byteadress
CMD[1] = ((addr & 0xFF000000) >>24 );
CMD[2] = ((addr & 0x00FF0000) >>16 );
CMD[3] = ((addr & 0x0000FF00) >>8 );
 
tmp = SDC_PutCommand (CMD); // send command to sdcard.
if (tmp != 0)
{
return(tmp);
}
#ifdef SSC_RX_FIFO
SSC_ClearRxFifo();
#endif
for (u8 a=0;a<100;a++) // wait until sdcard is ready
{
SSC_GetChar();
}
SSC_PutChar(0xFE); // send start of header to the SSC
for (u16 a=0;a<512;a++) // transmitt one sector (normaly 512bytes) of data to the sdcard.
{
SSC_PutChar(*Buffer++);
}
SSC_PutChar(0xFF); // write two bytes of crc to the sdcard (not used in spi-mode)
SSC_PutChar(0xFF);
#ifdef SSC_RX_FIFO
SSC_ClearRxFifo();
#endif
while (SSC_GetChar() != 0xff){}; // wait untile the sdcard is ready.
SSC_Disable(); // disable sdcard.
 
return(0);
}
 
 
 
//________________________________________________________________________________________________________________________________________
// Funtion: SDC_GetSector(u32 addr,u8*Buffer);
//
// Description: This function reads one sector of data from the SSC
//
//
// Returnvalue: none
//________________________________________________________________________________________________________________________________________
 
u8 SDC_GetSector(u32 addr,u8*Buffer)
{
u8 CMD[] = {0x51,0x00,0x00,0x00,0x00,0xFF};
addr = addr << 9; // convert sectoradress to byteadress.
 
CMD[1] = ((addr & 0xFF000000) >>24 );
CMD[2] = ((addr & 0x00FF0000) >>16 );
CMD[3] = ((addr & 0x0000FF00) >>8 );
 
SDC_GetBlock(CMD,Buffer,512); // read specified sector from sdcard.
 
return(0);
}
 
 
 
//________________________________________________________________________________________________________________________________________
// Funtion: SDC_GetBlock(void);
//
// Description: This function reads one block of data of s16 bytes from the SSC.
//
//
// Returnvalue: the function returns 0 if the initialisation was successfull otherwise the function returns an errorcode.
//________________________________________________________________________________________________________________________________________
 
void SDC_GetBlock(u8*CMD,u8*Buffer,u16 Bytes)
{
if (SDC_PutCommand (CMD) != 0) // Send command to the sdcard.
{
return;
}
#ifdef SSC_RX_FIFO
SSC_ClearRxFifo();
#endif
while (SSC_GetChar() != 0xfe){}; // wait until the sdcard is ready to transmitt data.
for (u16 a=0;a<Bytes;a++) // read the block from the SSC (normaly 512Bytes)
{
*Buffer++ = SSC_GetChar();
}
SSC_GetChar(); // Read two bytes CRC- checksum (not used in spi-mode)
SSC_GetChar();
SSC_Disable(); // disable sdcard.
}
 
 
 
/FollowMe/sdc.h
0,0 → 1,33
#ifndef _SDC_H_
#define _SDC_H_
 
extern u8 SDC_Init(void);
 
//________________________________________________________________________________________________________________________________________
//
// Functions needed for access to the sdcard.
//
//________________________________________________________________________________________________________________________________________
 
extern u8 SSC_GetChar(void);
extern void SSC_PutChar(u8);
extern void MMC_Read_Block(u8 *,u8 *,u16);
 
 
//________________________________________________________________________________________________________________________________________
//
// Functions needed internaly for the fat16 implementation
//
//________________________________________________________________________________________________________________________________________
 
extern u8 SDC_GetSector (u32,u8 *);
extern u8 SDC_PutSector (u32,u8 *);
extern u8 SDC_PutCommand (u8 *);
extern void SDC_GetBlock(u8 *CMD,u8 *Buffer,u16 Bytes);
 
 
#define nop() __asm__ __volatile__ ("nop" ::)
 
#endif
 
 
/FollowMe/ssc.c
0,0 → 1,166
#include <avr/io.h>
#include "fat16.h"
#include "ssc.h"
 
//________________________________________________________________________________________________________________________________________
// Module name: fat16.c
// Compiler used: avr-gcc 3.4.5
// Last Modifikation: 24.07.2007
// Version: 1.03
// Authors: Stephan Busker
// Description: Source files for access to the synchrnous serial channel.
// Copyright (C) 2007 Stephan Busker
//........................................................................................................................................
// Functions: extern void SSC_Init(void);
// extern u8 SSC_GetChar (void);
// extern void SSC_PutChar (u8 Byte);
// extern void SSC_Disable(void);
// extern void SSC_Enable(void);
//........................................................................................................................................
// ext. functions: extern u8 SDC_GetSector (u32,u8*);
// extern u8 SDC_PutSector (u32,u8*);
//........................................................................................................................................
//
// URL: www.Mikro-Control.de
// mailto: stephan.busker@mikro-control.de
//________________________________________________________________________________________________________________________________________
 
 
 
 
//________________________________________________________________________________________________________________________________________
// Funtion: SSC_Init(void);
//
// Description: This function initialises the synchronus serial channel to the sdcard.
//
//
// Returnvalue: none
//________________________________________________________________________________________________________________________________________
 
void SSC_Init(void)
{
MMC_Direction_REG &=~(1<<SPI_DI); // Set the direction of the ssc-port
MMC_Direction_REG |= (1<<SPI_Clock); // _______ _______
MMC_Direction_REG |= (1<<SPI_DO); // CS \________________________/
MMC_Direction_REG |= (1<<MMC_Chip_Select); //
MMC_Direction_REG |= (1<<SPI_SS); // ___ ___ ___
// clk __________/ \___/ \___/ \_________
//
SSC_Disable(); // ___ ___
// data_________/ \___________/ \___________
 
// initialise ssc, clock = Idel low
// devide clock by 32
SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR1)|(1<<CPOL); // Enable SSC in mastermode, invert clockpolarity (idle high)
SPSR = SPSR|(1<<SPI2X);
}
 
 
 
 
//________________________________________________________________________________________________________________________________________
// Funtion: void SSC_ClearRxFifo(void);
//
// Description: Clears the fifo of the ssc if the controller used has a builtin fifo.
//
//
// Returnvalue: none
//________________________________________________________________________________________________________________________________________
 
 
void SSC_ClearRxFifo(void)
{
// enter your code here to clear the rx-fifo of the ssc.
}
 
 
 
//________________________________________________________________________________________________________________________________________
// Funtion: SSC_GetChar(void);
//
// Description: This function reads one byte from the SSC
//
//
// Returnvalue: the byte received.
//________________________________________________________________________________________________________________________________________
 
u8 SSC_GetChar (void)
{
u8 Byte = 0;
 
SPDR = 0x00; // read one byte of data from the SSC
while(!(SPSR & (1<<SPIF))){}; // wait until the data has been read.
Byte = SPDR;
 
#ifdef __MMC_INTERFACE_INVERTED
return (~Byte);
#else
return (Byte); // the byte received
#endif
 
}
 
 
//________________________________________________________________________________________________________________________________________
// Funtion: SSC_PutChar(u8 Byte);
//
// Description: This function writes one byte to the SSC
//
//
// Returnvalue: none
//________________________________________________________________________________________________________________________________________
 
void SSC_PutChar (u8 Byte)
{
#ifdef __MMC_INTERFACE_INVERTED
SPDR = ~Byte; // send one byte of data to the SSC
#else
SPDR = Byte; // send one byte of data to the SSC
#endif
SPDR = ~Byte; // send one byte of data to the SSC
while(!(SPSR & (1<<SPIF))) // wait until data was send.
{
}
}
 
 
//________________________________________________________________________________________________________________________________________
// Funtion: SSC_Disable(void);
//
// Description: This function enables chipselect of the sdcard (active low)
//
//
// Returnvalue: none
//________________________________________________________________________________________________________________________________________
 
void SSC_Disable(void)
{
#ifdef __MMC_INTERFACE_INVERTED
MMC_Write &= ~(1<<MMC_Chip_Select); // disable chipselect of the sdcard (active low).
#else
MMC_Write |= (1<<MMC_Chip_Select); // enable chipselect of the sdcard (active low).
#endif
}
 
 
 
 
//________________________________________________________________________________________________________________________________________
// Funtion: SSC_Enable(void);
//
// Description: This function disables chipselect of the sdcard (active low)
//
//
// Returnvalue: none
//________________________________________________________________________________________________________________________________________
 
void SSC_Enable(void)
{
#ifdef __MMC_INTERFACE_INVERTED
MMC_Write |= (1<<MMC_Chip_Select); // enable chipselect of the sdcard (active low).
#else
MMC_Write &= ~(1<<MMC_Chip_Select); // disable chipselect of the sdcard (active low).
#endif
}
 
/FollowMe/ssc.h
0,0 → 1,42
#ifndef __SSC_H
#define __SSC_H
 
 
//-------------------------------------- Hardware specific definitions --------------------------------------
 
#define MMC_Write PORTB //Port an der die MMC/SD-card angeschlossen ist (SPI Port)
#define MMC_Read PINB
#define MMC_Direction_REG DDRB
 
 
#ifdef USE_SDLOGGER
#define __MMC_INTERFACE_INVERTED // the interface between the controller and the MMC/SD-card uses an inverting leveltranslator (transistorinverter)
#endif // and therefore the signals to or from the memorycard have to be inverted.
 
#ifdef USE_FOLLOWME // uses resitors, therefore its not inverted
//#define __MMC_INTERFACE_INVERTED // the interface between the controller and the MMC/SD-card uses an inverting leveltranslator (transistorinverter)
#endif
 
#define SPI_DI 6 //Port Pin that is connected to the DO of the MMC/SD-card
#define SPI_DO 5 //Port Pin that is connected to DI of the MMC/SD-card
#define SPI_Clock 7 //Port Pin that is connected the CLK of the MMC/SD-card
#define SPI_SS 4 //Slave Select is not used in SPI Master Mode, but must be defined
#define MMC_Chip_Select 4 //Port Pin an dem Chip Select der MMC/SD-Karte angeschlossen ist
 
 
//________________________________________________________________________________________________________________________________________
//
// Functions needed for accessing the sdcard.
//
//________________________________________________________________________________________________________________________________________
 
extern void SSC_Init(void);
extern u8 SSC_GetChar (void);
extern void SSC_PutChar (u8);
extern void SSC_Enable(void);
extern void SSC_Disable(void);
extern void SSC_ClearRxFifo(void);
 
 
 
#endif
/FollowMe/timer0.c
0,0 → 1,92
#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
 
#include "main.h"
 
volatile uint16_t CountMilliseconds = 0;
 
 
 
/*****************************************************/
/* Initialize Timer 0 */
/*****************************************************/
// timer 0 is used for the PWM generation to control the offset voltage at the air pressure sensor
// Its overflow interrupt routine is used to generate the beep signal and the flight control motor update rate
void TIMER0_Init(void)
{
uint8_t sreg = SREG;
 
// disable all interrupts before reconfiguration
cli();
 
// Timer/Counter 0 Control Register A
 
// Waveform Generation Mode is Fast PWM (Bits WGM02 = 0, WGM01 = 1, WGM00 = 1)
// Clear OC0A on Compare Match, set OC0A at BOTTOM, noninverting PWM (Bits COM0A1 = 1, COM0A0 = 0)
// Clear OC0B on Compare Match, set OC0B at BOTTOM, (Bits COM0B1 = 1, COM0B0 = 0)
TCCR0A &= ~((1<<COM0A0)|(1<<COM0B0));
TCCR0A |= (1<<COM0A1)|(1<<COM0B1)|(1<<WGM01)|(1<<WGM00);
 
// Timer/Counter 0 Control Register B
 
// set clock devider for timer 0 to SYSKLOCK/8 = 20MHz / 8 = 2.5MHz
// i.e. the timer increments from 0x00 to 0xFF with an update rate of 2.5 MHz
// hence the timer overflow interrupt frequency is 2.5 MHz / 256 = 9.765 kHz
 
// divider 8 (Bits CS02 = 0, CS01 = 1, CS00 = 0)
TCCR0B &= ~((1<<FOC0A)|(1<<FOC0B)|(1<<WGM02));
TCCR0B = (TCCR0B & 0xF8)|(0<<CS02)|(1<<CS01)|(0<<CS00);
 
// initialize the Output Compare Register A & B used for PWM generation on port PB3 & PB4
OCR0A = 0; // for PB3
OCR0B = 120; // for PB4
 
// init Timer/Counter 0 Register
TCNT0 = 0;
 
// Timer/Counter 0 Interrupt Mask Register
// enable timer overflow interrupt only
TIMSK0 &= ~((1<<OCIE0B)|(1<<OCIE0A));
TIMSK0 |= (1<<TOIE0);
 
SREG = sreg;
}
 
 
 
/*****************************************************/
/* Interrupt Routine of Timer 0 */
/*****************************************************/
ISR(TIMER0_OVF_vect) // 9.765 kHz
{
static uint8_t cnt = 0;
 
if(!cnt--) // every 10th run (9.765kHz/10 = 976Hz)
{
cnt = 9;
CountMilliseconds++; // increment millisecond counter
}
}
 
 
// -----------------------------------------------------------------------
uint16_t SetDelay (uint16_t t)
{
return(CountMilliseconds + t - 1);
}
 
// -----------------------------------------------------------------------
int8_t CheckDelay(uint16_t t)
{
return(((t - CountMilliseconds) & 0x8000) >> 8); // check sign bit
}
 
// -----------------------------------------------------------------------
void Delay_ms(uint16_t w)
{
unsigned int t_stop;
t_stop = SetDelay(w);
while (!CheckDelay(t_stop));
}
 
/FollowMe/timer0.h
0,0 → 1,14
#ifndef _TIMER0_H
#define _TIMER0_H
 
#include <inttypes.h>
 
extern volatile uint16_t CountMilliseconds;
 
extern void TIMER0_Init(void);
extern void Delay_ms(uint16_t w);
extern void Delay_ms_Mess(uint16_t w);
extern uint16_t SetDelay (uint16_t t);
extern int8_t CheckDelay (uint16_t t);
 
#endif //_TIMER0_H
/FollowMe/uart0.c
0,0 → 1,515
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Copyright (c) 04.2007 Holger Buss
// + only for non-profit use
// + www.MikroKopter.com
// + see the File "License.txt" for further Informations
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
#include <stdarg.h>
#include <string.h>
 
#include "main.h"
#include "menu.h"
#include "timer0.h"
#include "uart0.h"
#include "ubx.h"
#include "led.h"
 
 
#define FC_ADDRESS 1
#define NC_ADDRESS 2
#define MK3MAG_ADDRESS 3
 
#define FM_ADDRESS 10 // FOLLOW ME
 
#define FALSE 0
#define TRUE 1
 
//int8_t test __attribute__ ((section (".noinit")));
uint8_t Request_VerInfo = FALSE;
uint8_t Request_Display = FALSE;
uint8_t Request_Display1 = FALSE;
uint8_t Request_ExternalControl = FALSE;
uint8_t Request_DebugData = FALSE;
uint8_t Request_DebugLabel = 255;
uint8_t DisplayLine = 0;
 
volatile uint8_t txd_buffer[TXD_BUFFER_LEN];
volatile uint8_t rxd_buffer_locked = FALSE;
volatile uint8_t rxd_buffer[RXD_BUFFER_LEN];
volatile uint8_t txd_complete = TRUE;
volatile uint8_t ReceivedBytes = 0;
volatile uint8_t *pRxData = 0;
volatile uint8_t RxDataLen = 0;
 
uint8_t PcAccess = 100;
 
ExternControl_t ExternControl;
DebugOut_t DebugOut;
UART_VersionInfo_t UART_VersionInfo;
 
uint16_t DebugData_Timer;
uint16_t DebugData_Interval = 500; // in 1ms
 
 
const uint8_t ANALOG_LABEL[32][16] =
{
//1234567890123456
"Debug0 ", //0
"Debug1 ",
"Debug2 ",
"Debug3 ",
"Debug4 ",
"Debug5 ", //5
"Debug6 ",
"Debug7 ",
"Debug8 ",
"Debug9 ",
"Debug10 ", //10
"Debug11 ",
"Debug12 ",
"Debug13 ",
"Debug14 ",
"Debug15 ", //15
"Debug16 ",
"Debug17 ",
"Debug18 ",
"Debug19 ",
"Debug20 ", //20
"Debug21 ",
"Debug22 ",
"Debug23 ",
"Debug24 ",
"Debug25 ", //25
"Debug26 ",
"Debug27 ",
"Debug28 ",
"Debug29 ",
"Debug30 ", //30
"Debug31 "
};
 
 
 
/****************************************************************/
/* Initialization of the USART0 */
/****************************************************************/
void USART0_Init (void)
{
uint8_t sreg = SREG;
uint16_t ubrr = (uint16_t) ((uint32_t) SYSCLK/(8 * USART0_BAUD) - 1);
 
// disable all interrupts before configuration
cli();
 
// disable RX-Interrupt
UCSR0B &= ~(1 << RXCIE0);
// disable TX-Interrupt
UCSR0B &= ~(1 << TXCIE0);
 
// set direction of RXD0 and TXD0 pins
// set RXD0 (PD0) as an input pin
PORTD |= (1 << PORTD0);
DDRD &= ~(1 << DDD0);
// set TXD0 (PD1) as an output pin
PORTD |= (1 << PORTD1);
DDRD |= (1 << DDD1);
 
// USART0 Baud Rate Register
// set clock divider
UBRR0H = (uint8_t)(ubrr >> 8);
UBRR0L = (uint8_t)ubrr;
 
// USART0 Control and Status Register A, B, C
 
// enable double speed operation in
UCSR0A |= (1 << U2X0);
// enable receiver and transmitter in
UCSR0B = (1 << TXEN0) | (1 << RXEN0);
// set asynchronous mode
UCSR0C &= ~(1 << UMSEL01);
UCSR0C &= ~(1 << UMSEL00);
// no parity
UCSR0C &= ~(1 << UPM01);
UCSR0C &= ~(1 << UPM00);
// 1 stop bit
UCSR0C &= ~(1 << USBS0);
// 8-bit
UCSR0B &= ~(1 << UCSZ02);
UCSR0C |= (1 << UCSZ01);
UCSR0C |= (1 << UCSZ00);
 
// flush receive buffer
while ( UCSR0A & (1<<RXC0) ) UDR0;
 
// enable interrupts at the end
// enable RX-Interrupt
UCSR0B |= (1 << RXCIE0);
// enable TX-Interrupt
UCSR0B |= (1 << TXCIE0);
 
// initialize the debug timer
DebugData_Timer = SetDelay(DebugData_Interval);
 
// unlock rxd_buffer
rxd_buffer_locked = FALSE;
pRxData = 0;
RxDataLen = 0;
 
// no bytes to send
txd_complete = TRUE;
 
UART_VersionInfo.SWMajor = VERSION_MAJOR;
UART_VersionInfo.SWMinor = VERSION_MINOR;
UART_VersionInfo.SWPatch = VERSION_PATCH;
UART_VersionInfo.ProtoMajor = VERSION_SERIAL_MAJOR;
UART_VersionInfo.ProtoMinor = VERSION_SERIAL_MINOR;
 
// restore global interrupt flags
SREG = sreg;
}
 
/****************************************************************/
/* USART0 transmitter ISR */
/****************************************************************/
ISR(USART0_TX_vect)
{
static uint16_t ptr_txd_buffer = 0;
uint8_t tmp_tx;
if(!txd_complete) // transmission not completed
{
ptr_txd_buffer++; // die [0] wurde schon gesendet
tmp_tx = txd_buffer[ptr_txd_buffer];
// if terminating character or end of txd buffer was reached
if((tmp_tx == '\r') || (ptr_txd_buffer == TXD_BUFFER_LEN))
{
ptr_txd_buffer = 0; // reset txd pointer
txd_complete = 1; // stop transmission
}
UDR0 = tmp_tx; // send current byte will trigger this ISR again
}
// transmission completed
else ptr_txd_buffer = 0;
}
 
/****************************************************************/
/* USART0 receiver ISR */
/****************************************************************/
ISR(USART0_RX_vect)
{
static uint16_t crc;
static uint8_t ptr_rxd_buffer = 0;
uint8_t crc1, crc2;
uint8_t c;
 
c = UDR0; // catch the received byte
 
if(rxd_buffer_locked) return; // if rxd buffer is locked immediately return
 
// the rxd buffer is unlocked
if((ptr_rxd_buffer == 0) && (c == '#')) // if rxd buffer is empty and syncronisation character is received
{
rxd_buffer[ptr_rxd_buffer++] = c; // copy 1st byte to buffer
crc = c; // init crc
}
#if 0
else if (ptr_rxd_buffer == 1) // handle address
{
rxd_buffer[ptr_rxd_buffer++] = c; // copy byte to rxd buffer
crc += c; // update crc
}
#endif
else if (ptr_rxd_buffer < RXD_BUFFER_LEN) // collect incomming bytes
{
if(c != '\r') // no termination character
{
rxd_buffer[ptr_rxd_buffer++] = c; // copy byte to rxd buffer
crc += c; // update crc
}
else // termination character was received
{
// the last 2 bytes are no subject for checksum calculation
// they are the checksum itself
crc -= rxd_buffer[ptr_rxd_buffer-2];
crc -= rxd_buffer[ptr_rxd_buffer-1];
// calculate checksum from transmitted data
crc %= 4096;
crc1 = '=' + crc / 64;
crc2 = '=' + crc % 64;
// compare checksum to transmitted checksum bytes
if((crc1 == rxd_buffer[ptr_rxd_buffer-2]) && (crc2 == rxd_buffer[ptr_rxd_buffer-1]))
{ // checksum valid
rxd_buffer[ptr_rxd_buffer] = '\r'; // set termination character
ReceivedBytes = ptr_rxd_buffer + 1;// store number of received bytes
rxd_buffer_locked = TRUE; // lock the rxd buffer
// if 2nd byte is an 'R' enable watchdog that will result in an reset
if(rxd_buffer[2] == 'R') {wdt_enable(WDTO_250MS);} // Reset-Commando
}
else
{ // checksum invalid
rxd_buffer_locked = FALSE; // unlock rxd buffer
}
ptr_rxd_buffer = 0; // reset rxd buffer pointer
}
}
else // rxd buffer overrun
{
ptr_rxd_buffer = 0; // reset rxd buffer
rxd_buffer_locked = FALSE; // unlock rxd buffer
}
 
}
 
 
// --------------------------------------------------------------------------
void AddCRC(uint16_t datalen)
{
uint16_t tmpCRC = 0, i;
for(i = 0; i < datalen; i++)
{
tmpCRC += txd_buffer[i];
}
tmpCRC %= 4096;
txd_buffer[i++] = '=' + tmpCRC / 64;
txd_buffer[i++] = '=' + tmpCRC % 64;
txd_buffer[i++] = '\r';
txd_complete = FALSE;
UDR0 = txd_buffer[0]; // initiates the transmittion (continued in the TXD ISR)
}
 
 
 
// --------------------------------------------------------------------------
void SendOutData(uint8_t cmd, uint8_t addr, uint8_t numofbuffers, ...) // uint8_t *pdata, uint8_t len, ...
{
va_list ap;
uint16_t pt = 0;
uint8_t a,b,c;
uint8_t ptr = 0;
 
uint8_t *pdata = 0;
int len = 0;
 
txd_buffer[pt++] = '#'; // Start character
txd_buffer[pt++] = 'a' + addr; // Address (a=0; b=1,...)
txd_buffer[pt++] = cmd; // Command
 
va_start(ap, numofbuffers);
if(numofbuffers)
{
pdata = va_arg(ap, uint8_t*);
len = va_arg(ap, int);
ptr = 0;
numofbuffers--;
}
 
while(len)
{
if(len)
{
a = pdata[ptr++];
len--;
if((!len) && numofbuffers)
{
pdata = va_arg(ap, uint8_t*);
len = va_arg(ap, int);
ptr = 0;
numofbuffers--;
}
}
else a = 0;
if(len)
{
b = pdata[ptr++];
len--;
if((!len) && numofbuffers)
{
pdata = va_arg(ap, uint8_t*);
len = va_arg(ap, int);
ptr = 0;
numofbuffers--;
}
}
else b = 0;
if(len)
{
c = pdata[ptr++];
len--;
if((!len) && numofbuffers)
{
pdata = va_arg(ap, uint8_t*);
len = va_arg(ap, int);
ptr = 0;
numofbuffers--;
}
}
else c = 0;
txd_buffer[pt++] = '=' + (a >> 2);
txd_buffer[pt++] = '=' + (((a & 0x03) << 4) | ((b & 0xf0) >> 4));
txd_buffer[pt++] = '=' + (((b & 0x0f) << 2) | ((c & 0xc0) >> 6));
txd_buffer[pt++] = '=' + ( c & 0x3f);
}
va_end(ap);
AddCRC(pt); // add checksum after data block and initates the transmission
}
 
 
// --------------------------------------------------------------------------
void Decode64(void)
{
uint8_t a,b,c,d;
uint8_t x,y,z;
uint8_t ptrIn = 3;
uint8_t ptrOut = 3;
uint8_t len = ReceivedBytes - 6;
 
while(len)
{
a = rxd_buffer[ptrIn++] - '=';
b = rxd_buffer[ptrIn++] - '=';
c = rxd_buffer[ptrIn++] - '=';
d = rxd_buffer[ptrIn++] - '=';
//if(ptrIn > ReceivedBytes - 3) break;
 
x = (a << 2) | (b >> 4);
y = ((b & 0x0f) << 4) | (c >> 2);
z = ((c & 0x03) << 6) | d;
 
if(len--) rxd_buffer[ptrOut++] = x; else break;
if(len--) rxd_buffer[ptrOut++] = y; else break;
if(len--) rxd_buffer[ptrOut++] = z; else break;
}
pRxData = &rxd_buffer[3];
RxDataLen = ptrOut - 3;
}
 
 
// --------------------------------------------------------------------------
void USART0_ProcessRxData(void)
{
// if data in the rxd buffer are not locked immediately return
if(!rxd_buffer_locked) return;
 
Decode64(); // decode data block in rxd_buffer
 
 
switch(rxd_buffer[1] - 'a')
{
case FM_ADDRESS:
 
switch(rxd_buffer[2])
{
default:
//unsupported command received
break;
} // case FC_ADDRESS:
 
default: // any Slave Address
 
switch(rxd_buffer[2])
{
case 'a':// request for labels of the analog debug outputs
Request_DebugLabel = pRxData[0];
if(Request_DebugLabel > 31) Request_DebugLabel = 31;
PcAccess = 255;
break;
 
case 'h':// request for display columns
PcAccess = 255;
RemoteKeys |= pRxData[0];
if(RemoteKeys) DisplayLine = 0;
Request_Display = TRUE;
break;
 
case 'l':// request for display columns
PcAccess = 255;
MenuItem = pRxData[0];
Request_Display1 = TRUE;
break;
 
case 'v': // request for version and board release
Request_VerInfo = TRUE;
break;
 
case 'd': // request for the debug data
DebugData_Interval = (uint16_t) pRxData[0] * 10;
if(DebugData_Interval > 0) Request_DebugData = TRUE;
break;
 
case 'g':// get external control data
Request_ExternalControl = TRUE;
break;
 
default:
LEDRED_TOGGLE;
//unsupported command received
break;
}
break; // default:
}
// unlock the rxd buffer after processing
pRxData = 0;
RxDataLen = 0;
rxd_buffer_locked = FALSE;
}
 
//############################################################################
//Routine für die Serielle Ausgabe
int16_t uart_putchar (int8_t c)
//############################################################################
{
if (c == '\n')
uart_putchar('\r');
// wait until previous character was send
loop_until_bit_is_set(UCSR0A, UDRE0);
// send character
UDR0 = c;
return (0);
}
 
 
//---------------------------------------------------------------------------------------------
void USART0_TransmitTxData(void)
{
if(!txd_complete) return;
 
if(Request_VerInfo && txd_complete)
{
SendOutData('V', FM_ADDRESS, 1, (uint8_t *) &UART_VersionInfo, sizeof(UART_VersionInfo));
Request_VerInfo = FALSE;
}
if(Request_Display && txd_complete)
{
LCD_PrintMenu();
SendOutData('H', FM_ADDRESS, 2, &DisplayLine, sizeof(DisplayLine), &DisplayBuff[DisplayLine * 20], 20);
DisplayLine++;
if(DisplayLine >= 4) DisplayLine = 0;
Request_Display = FALSE;
}
if(Request_Display1 && txd_complete)
{
LCD_PrintMenu();
SendOutData('L', FM_ADDRESS, 3, &MenuItem, sizeof(MenuItem), &MaxMenuItem, sizeof(MaxMenuItem), DisplayBuff, sizeof(DisplayBuff));
Request_Display1 = FALSE;
}
if(Request_DebugLabel != 0xFF) // Texte für die Analogdaten
{
SendOutData('A', FM_ADDRESS, 2, (uint8_t *) &Request_DebugLabel, sizeof(Request_DebugLabel), ANALOG_LABEL[Request_DebugLabel], 16);
Request_DebugLabel = 0xFF;
}
if(Request_ExternalControl && txd_complete)
{
SendOutData('G', FM_ADDRESS, 1,(uint8_t *) &ExternControl, sizeof(ExternControl));
Request_ExternalControl = FALSE;
}
if( ((DebugData_Interval && CheckDelay(DebugData_Timer)) || Request_DebugData) && txd_complete)
{
SendOutData('D', FM_ADDRESS, 1,(uint8_t *) &DebugOut, sizeof(DebugOut));
DebugData_Timer = SetDelay(DebugData_Interval);
Request_DebugData = FALSE;
}
}
 
/FollowMe/uart0.h
0,0 → 1,59
#ifndef _UART0_H
#define _UART0_H
 
#define RXD_BUFFER_LEN 150
// must be at least 4('#'+Addr+'CmdID'+'\r')+ (80 * 4)/3 = 111 bytes
#define TXD_BUFFER_LEN 150
#define RXD_BUFFER_LEN 150
 
#include <inttypes.h>
 
//Baud rate of the USART
#define USART0_BAUD 57600
 
 
extern void USART0_Init (void);
extern void USART0_TransmitTxData(void);
extern void USART0_ProcessRxData(void);
extern int16_t uart_putchar(int8_t c);
 
extern uint8_t PcAccess;
extern uint8_t RemotePollDisplayLine;
 
typedef struct
{
uint8_t Digital[2];
uint8_t RemoteButtons;
int8_t Nick;
int8_t Roll;
int8_t Yaw;
uint8_t Gas;
int8_t Height;
uint8_t free;
uint8_t Frame;
uint8_t Config;
} __attribute__((packed)) ExternControl_t;
 
extern ExternControl_t ExternControl;
 
 
typedef struct
{
uint8_t Digital[2];
uint16_t Analog[32]; // Debugvalues
} __attribute__((packed)) DebugOut_t;
 
extern DebugOut_t DebugOut;
 
typedef struct
{
uint8_t SWMajor;
uint8_t SWMinor;
uint8_t ProtoMajor;
uint8_t ProtoMinor;
uint8_t SWPatch;
uint8_t Reserved[5];
} __attribute__((packed)) UART_VersionInfo_t;
 
 
#endif //_UART0_H
/FollowMe/uart1.c
0,0 → 1,94
#include <avr/io.h>
#include <avr/interrupt.h>
 
#include "main.h"
#include "uart1.h"
#include "ubx.h"
 
 
/****************************************************************/
/* Initialization of the USART1 */
/****************************************************************/
void USART1_Init (void)
{
// USART1 Control and Status Register A, B, C and baud rate register
uint8_t sreg = SREG;
uint16_t ubrr = (uint16_t) ((uint32_t) SYSCLK/(8 * USART1_BAUD) - 1);
 
// disable all interrupts before reconfiguration
cli();
 
// disable RX-Interrupt
UCSR1B &= ~(1 << RXCIE1);
// disable TX-Interrupt
UCSR1B &= ~(1 << TXCIE1);
// disable DRE-Interrupt
UCSR1B &= ~(1 << UDRIE1);
 
// set direction of RXD1 and TXD1 pins
// set RXD1 (PD2) as an input pin
PORTD |= (1 << PORTD2);
DDRD &= ~(1 << DDD2);
 
// set TXD1 (PD3) as an output pin
PORTD |= (1 << PORTD3);
DDRD |= (1 << DDD3);
 
// USART0 Baud Rate Register
// set clock divider
UBRR1H = (uint8_t)(ubrr>>8);
UBRR1L = (uint8_t)ubrr;
 
// enable double speed operation
UCSR1A |= (1 << U2X1);
// enable receiver and transmitter
UCSR1B = (1 << TXEN1) | (1 << RXEN1);
// set asynchronous mode
UCSR1C &= ~(1 << UMSEL11);
UCSR1C &= ~(1 << UMSEL10);
// no parity
UCSR1C &= ~(1 << UPM11);
UCSR1C &= ~(1 << UPM10);
// 1 stop bit
UCSR1C &= ~(1 << USBS1);
// 8-bit
UCSR1B &= ~(1 << UCSZ12);
UCSR1C |= (1 << UCSZ11);
UCSR1C |= (1 << UCSZ10);
 
// flush receive buffer explicit
while ( UCSR1A & (1<<RXC1) ) UDR1;
 
// enable interrupts at the end
// enable RX-Interrupt
UCSR1B |= (1 << RXCIE1);
// enable TX-Interrupt
UCSR1B |= (1 << TXCIE1);
// enable DRE interrupt
//UCSR1B |= (1 << UDRIE1);
 
 
// restore global interrupt flags
SREG = sreg;
 
}
 
/****************************************************************/
/* USART1 transmitter ISR */
/****************************************************************/
/*ISR(USART1_TX_vect)
{
 
}
*/
/****************************************************************/
/* USART1 receiver ISR */
/****************************************************************/
ISR(USART1_RX_vect)
{
uint8_t c;
c = UDR1; // get data byte
 
ubx_parser(c); // and put it into the ubx protocol parser
 
}
/FollowMe/uart1.h
0,0 → 1,25
#ifndef _UART1_H
#define _UART1_H
 
#define USART1_BAUD 57600
 
/*
Initialize the USART und activate the receiver and transmitter
as well as the receive-interrupt. The IO-FIFOs are initialized.
The global interrupt-enable-flag (I-Bit in SREG) is not changed
*/
extern void USART1_Init (void);
 
/*
The character c is stored in the output buffer. If the character was pushed sucessfully to
the output buffer then the return value is 1. In case of an output buffer overflow the return value is 0.
The isr is activated, which will send the data from the outbut buffer to the UART.
*/
extern int USART1_putc (const uint8_t c);
 
/*
extern uint8_t USART1_getc_wait(void);
extern int16_t USART1_getc_nowait(void);
*/
 
#endif //_UART1_H
/FollowMe/ubx.c
0,0 → 1,237
#include <inttypes.h>
 
#include "ubx.h"
#include <avr/io.h>
 
 
// ubx protocol parser state machine
#define UBXSTATE_IDLE 0
#define UBXSTATE_SYNC1 1
#define UBXSTATE_SYNC2 2
#define UBXSTATE_CLASS 3
#define UBXSTATE_LEN1 4
#define UBXSTATE_LEN2 5
#define UBXSTATE_DATA 6
#define UBXSTATE_CKA 7
#define UBXSTATE_CKB 8
 
// ublox protocoll identifier
#define UBX_CLASS_NAV 0x01
 
#define UBX_ID_POSLLH 0x02
#define UBX_ID_SOL 0x06
#define UBX_ID_VELNED 0x12
 
#define UBX_SYNC1_CHAR 0xB5
#define UBX_SYNC2_CHAR 0x62
 
typedef struct {
uint32_t ITOW; // ms GPS Millisecond Time of Week
int32_t Frac; // ns remainder of rounded ms above
int16_t week; // GPS week
uint8_t GPSfix; // GPSfix Type, range 0..6
uint8_t Flags; // Navigation Status Flags
int32_t ECEF_X; // cm ECEF X coordinate
int32_t ECEF_Y; // cm ECEF Y coordinate
int32_t ECEF_Z; // cm ECEF Z coordinate
uint32_t PAcc; // cm 3D Position Accuracy Estimate
int32_t ECEFVX; // cm/s ECEF X velocity
int32_t ECEFVY; // cm/s ECEF Y velocity
int32_t ECEFVZ; // cm/s ECEF Z velocity
uint32_t SAcc; // cm/s Speed Accuracy Estimate
uint16_t PDOP; // 0.01 Position DOP
uint8_t res1; // reserved
uint8_t numSV; // Number of SVs used in navigation solution
uint32_t res2; // reserved
Status_t Status;
} UBX_SOL_t;
 
typedef struct {
uint32_t ITOW; // ms GPS Millisecond Time of Week
int32_t LON; // 1e-07 deg Longitude
int32_t LAT; // 1e-07 deg Latitude
int32_t HEIGHT; // mm Height above Ellipsoid
int32_t HMSL; // mm Height above mean sea level
uint32_t Hacc; // mm Horizontal Accuracy Estimate
uint32_t Vacc; // mm Vertical Accuracy Estimate
Status_t Status;
} UBX_POSLLH_t;
 
typedef struct {
uint32_t ITOW; // ms GPS Millisecond Time of Week
int32_t VEL_N; // cm/s NED north velocity
int32_t VEL_E; // cm/s NED east velocity
int32_t VEL_D; // cm/s NED down velocity
uint32_t Speed; // cm/s Speed (3-D)
uint32_t GSpeed; // cm/s Ground Speed (2-D)
int32_t Heading; // 1e-05 deg Heading 2-D
uint32_t SAcc; // cm/s Speed Accuracy Estimate
uint32_t CAcc; // deg Course / Heading Accuracy Estimate
Status_t Status;
} UBX_VELNED_t;
 
UBX_SOL_t UbxSol = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, INVALID};
UBX_POSLLH_t UbxPosLlh = {0,0,0,0,0,0,0, INVALID};
UBX_VELNED_t UbxVelNed = {0,0,0,0,0,0,0,0,0, INVALID};
GPS_INFO_t GPSInfo = {0,0,0,0,0,0,0,0,0,0, INVALID};
 
volatile uint8_t GPSTimeout = 0;
 
void UpdateGPSInfo (void)
{
 
if ((UbxSol.Status == NEWDATA) && (UbxPosLlh.Status == NEWDATA) && (UbxVelNed.Status == NEWDATA))
{
if(GPSInfo.status != NEWDATA)
{
GPSInfo.status = INVALID;
// NAV SOL
GPSInfo.flags = UbxSol.Flags;
GPSInfo.satfix = UbxSol.GPSfix;
GPSInfo.satnum = UbxSol.numSV;
GPSInfo.PAcc = UbxSol.PAcc;
GPSInfo.VAcc = UbxSol.SAcc;
// NAV POSLLH
GPSInfo.longitude = UbxPosLlh.LON;
GPSInfo.latitude = UbxPosLlh.LAT;
GPSInfo.altitude = UbxPosLlh.HEIGHT;
 
GPSInfo.veleast = UbxVelNed.VEL_E;
GPSInfo.velnorth = UbxVelNed.VEL_N;
GPSInfo.veltop = -UbxVelNed.VEL_D;
GPSInfo.velground = UbxVelNed.GSpeed;
 
GPSInfo.status = NEWDATA;
 
}
// set state to collect new data
UbxSol.Status = PROCESSED; // never update old data
UbxPosLlh.Status = PROCESSED; // never update old data
UbxVelNed.Status = PROCESSED; // never update old data
}
 
 
}
 
 
// this function should be called within the UART RX ISR
void ubx_parser(uint8_t c)
{
static uint8_t ubxstate = UBXSTATE_IDLE;
static uint8_t cka, ckb;
static uint16_t msglen;
static int8_t *ubxP, *ubxEp, *ubxSp; // pointers to data currently transfered
 
switch(ubxstate)
{
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 = (int8_t *)&UbxPosLlh; // data start pointer
ubxEp = (int8_t *)(&UbxPosLlh + 1); // data end pointer
ubxSp = (int8_t *)&UbxPosLlh.Status; // status pointer
break;
 
case UBX_ID_SOL: // navigation solution
ubxP = (int8_t *)&UbxSol; // data start pointer
ubxEp = (int8_t *)(&UbxSol + 1); // data end pointer
ubxSp = (int8_t *)&UbxSol.Status; // status pointer
break;
 
case UBX_ID_VELNED: // velocity vector in tangent plane
ubxP = (int8_t *)&UbxVelNed; // data start pointer
ubxEp = (int8_t *)(&UbxVelNed + 1); // data end pointer
ubxSp = (int8_t *)&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 = c;
cka += c;
ckb += cka;
ubxstate = UBXSTATE_LEN2;
break;
 
case UBXSTATE_LEN2: // 2nd message length byte
msglen += ((uint16_t)c)<<8;
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 )
{
UpdateGPSInfo(); //update GPS info respectively
ubxstate = UBXSTATE_IDLE;
}
else // data invalid or allready processd
{
*ubxSp = INVALID;
ubxstate = UBXSTATE_DATA;
}
break;
 
case UBXSTATE_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
UpdateGPSInfo(); //update GPS info respectively
GPSTimeout = 255;
}
else
{ // if checksum not fit then set data invalid
*ubxSp = INVALID;
}
ubxstate = UBXSTATE_IDLE; // ready to parse new data
break;
 
default: // unknown ubx state
ubxstate = UBXSTATE_IDLE;
break;
}
 
}
 
 
/FollowMe/ubx.h
0,0 → 1,59
#ifndef _UBX_H
#define _UBX_H
 
#include <inttypes.h>
 
 
typedef enum
{
INVALID,
NEWDATA,
PROCESSED
} Status_t;
 
// 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)
 
 
/* enable the UBX protocol at the gps receiver with the following messages enabled
01-02 NAV - POSLLH
01-06 Nav - SOL
01-12 NAV - VELNED */
 
typedef struct
{
uint8_t flags; // flags
uint8_t satnum; // number of satelites
uint8_t satfix; // type of satfix
int32_t longitude; // in 1e-07 deg
int32_t latitude; // in 1e-07 deg
int32_t altitude; // in mm
uint32_t PAcc; // in cm 3d position accuracy
int32_t velnorth; // in cm/s
int32_t veleast; // in cm/s
int32_t veltop; // in cm/s
uint32_t velground; // 2D ground speed in cm/s
uint32_t VAcc; // in cm/s 3d velocity accuracy
Status_t status; // status of data: invalid | valid
} GPS_INFO_t;
 
//here you will find the current gps info
extern GPS_INFO_t GPSInfo; // measured position (last gps record)
 
// this variable should be decremted by the application
extern volatile uint8_t GPSTimeout; // is reset to 255 if a new UBX msg was received
 
// this function should be called within the UART RX ISR
extern void ubx_parser(uint8_t c);
 
#endif //_UBX_H