C1541-III mbed edition

Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
gertk
Date:
Mon Aug 22 05:48:51 2011 +0000
Child:
1:0cbbb66a6100
Commit message:
very early test version, works only with FAT16 formatted sd cards

Changed in this revision

D64_decoder.c Show annotated file Show diff for this revision Revisions of this file
D64_decoder.h Show annotated file Show diff for this revision Revisions of this file
IEC_bus.c Show annotated file Show diff for this revision Revisions of this file
IEC_bus.h Show annotated file Show diff for this revision Revisions of this file
T64_decoder.c Show annotated file Show diff for this revision Revisions of this file
T64_decoder.h Show annotated file Show diff for this revision Revisions of this file
ata.c Show annotated file Show diff for this revision Revisions of this file
ata.h Show annotated file Show diff for this revision Revisions of this file
delay.c Show annotated file Show diff for this revision Revisions of this file
delay.h Show annotated file Show diff for this revision Revisions of this file
fat.c Show annotated file Show diff for this revision Revisions of this file
fat.h Show annotated file Show diff for this revision Revisions of this file
hardware.c Show annotated file Show diff for this revision Revisions of this file
hardware.h Show annotated file Show diff for this revision Revisions of this file
main.c Show annotated file Show diff for this revision Revisions of this file
main.h Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/D64_decoder.c	Mon Aug 22 05:48:51 2011 +0000
@@ -0,0 +1,765 @@
+/*----------------------------------------------------------------------------------*/
+/*    These routines are designed to decode a file according the D64 format           */
+/*----------------------------------------------------------------------------------*/
+/*                                                                                  */
+
+/*  History:                                                                        
+    -------- 
+    2007-03-30    added a buffer pointer to the D64blockread function, which is now called D64blockread_new, which gives some room to test the function before changing the entire software at 1000 places... to find out after 3 months i made a small mistake, therefore a temporarily routine with a different name
+                and for d64blockwrite the same
+    2007-03-25    changed the independent BAM_buffer to the DOS_buffer at buffer location #4 (as on a real 1541 drive)
+    2006-11-21    added the truncation of everything behind the , or = sign in a save filename (or actually when adding a directory entry)
+    2006-10-25    fixed bug in the seekfreeblock, the routine pointed a free block inside track18, this is evil. This bug is fixed. Now a free block for saving purposes will never be allocated in track-18
+    2006-09-09    scratch routine was not completed, it did not set the flags of the used blocks to FREE, FIXED
+    2006-09-07    write is maturing, now it is possible to write multiple files to one disk without problems, stil required is working on related actions like file checking error handling
+    2006-09-05     a tiny error in buffer copying caused mutilation of the BAM (disk label), fixed
+                D64SeekFreeBlock did not return correct info causing the previous odd block to be overwritten 
+                added routines "read/write-freeblockspertrack"
+    2006-09-04    a small step further with write support, calculation of the track-sector flag was one byte off, fixed
+    2006-09-03    oopsie... accidentally swapped the names of the D64 read and write routines, creating all sorts of wierd problems
+    2006-09-02    worked on the D64BAMflagtest routine...
+    2006-09-01    renamed all routines within this source, now ALL routines start with D64      
+    2006-08-28    added 2 more routines to calculate track and sector from block address and vice versa
+    2006-07-09    it appears that some files use track=0 sector=0 to indicate that this was the last directory block
+                this is not compatible with the docs I found which clearly states track=0 sector=255
+    2006-02-03    embedded the calcbyteaddress routine inside a file read routine, makes D64 file access sourcecode much nicer to read
+    2006-02-02    improvements in code layout... i.o.w. making it more readable
+    2005-09-23    raw design of D64 decoder
+    2005-10-18    minor modifications in textual layout (code-cleanup)
+*/
+
+/*  TO DO:                                                                          
+    ------
+    - routine "D64LoadFile_X_Bytes" needs to be updated using the 'newer' D64 routines
+
+    - seek functie plaatsen in "fat16_on_PIC18.C", daar hoort 'ie thuis en niet in de D64 decoding routines
+    - routines die gebruik maken van stringbuffers in minder code opschrijven        
+*/
+
+/*----------------------------------------------------------------------------------*/
+
+extern void OutputToRS232();
+extern void OutputToLCD();
+
+/*--------------------------------------------------------*/
+/*                        includes                        */
+/*--------------------------------------------------------*/
+#include <mbed.h>
+#include <stdio.h>
+#include <main.h>
+#include <hardware.h>
+#include <fat.h>
+#include <delay.h>
+#include <D64_decoder.h>
+
+/*--------------------------------------------------------*/
+/*                   (tunable) constants                  */ 
+/*--------------------------------------------------------*/
+
+
+/*--------------------------------------------------------*/
+/*                        constants                       */   
+/*--------------------------------------------------------*/
+#define            FALSE            0                /*FALSE*/
+#define            TRUE            1                /*TRUE*/
+
+/*--------------------------------------------------------*/
+/*                         table                          */
+/*--------------------------------------------------------*/
+/*SPT (SectorsPerTrack) decoding table*/
+/*Attention: TRACK counting starts at '1' (not at '0')*/
+/*           SECTOR counting starts at '0' (not at '1')*/
+const unsigned char SPT[41]= {0,                                                    /*track 0 does not excist*/
+                             21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,/*track 1-17*/
+                             19,19,19,19,19,19,19,                                /*track 18-24*/
+                             18,18,18,18,18,18,                                    /*track 25-30*/
+                             17,17,17,17,17,17,17,17,17,17};                        /*track 31-40*/
+
+
+/*variables*/
+extern struct            file2TYPE             file;            /*file handle*/
+extern struct            directory_entry        dir_entry;        /*directory structure inside the D64*/
+
+extern unsigned char    error_code;                /*this holds the error-message generated by one of the disk routines*/
+extern unsigned char    LastTrack;                /*last accessed track variable*/
+extern unsigned char    LastSector;                /*last accessed sector variable*/
+
+/*--------------------------------------------------------*/
+/*                     local functions                    */
+/*--------------------------------------------------------*/
+
+/*************************************************************************************/
+/*External functions*/
+/*************************************************************************************/
+/*this routine clears the entire block_buffer*/
+void Clear_RAM_buffer(void)
+{
+    unsigned char lp;
+
+    lp=0;
+    do
+    {
+        RAM_buffer[lp] = 0x00;
+        lp++;
+    }
+    while(lp!=0);
+}
+
+
+/*this routine will calculate the track and sector based on the given (256bytes, since D64 blocks are 256bytes) block*/
+void D64ConvertBlockToTrackSector(unsigned int block, unsigned char *track, unsigned char *sector)
+{
+    *track = 1;        /*Attention:  track starts at 1 */
+    *sector = 0;    /*Attention: sector starts at 0 */
+    while(block)
+    {
+        *sector = *sector + 1;
+        if (*sector > (SPT[*track] - 1))
+        {
+            *sector = 0;
+            *track = *track + 1;            
+        }
+        block--;
+    }
+}
+
+/*calculate the D64 block (D64 blocksize is 256 bytes) address determined by the D64-track-sector-byte numbers*/
+unsigned int D64ConvertTrackSectorToBlock(unsigned char track, unsigned char sector)
+{
+    unsigned int block;
+
+    block = 0;
+    while(track--)
+    {
+        block = block + SPT[track];        /*retrieve number of sector per track from table and multiply the number of sectors with 256 (256bytes per sector), add this to the total*/
+    }
+    block = block + sector;
+    return(block);
+}
+
+/*this routine will read the BAM (and stores it in the BAM_buffer (DOS_buffer[4].buffer[..]), this should be done everytime a new D64 image is selected*/
+void D64ReadBAM(void)
+{
+    /*this routine only supports 35 track disks, since I lack the knowledge of 40 track size disks*/
+    
+    unsigned int lp, block, offset;
+
+    block = D64ConvertTrackSectorToBlock(18,0);                /*the block number is a 256byte blocksize, so for a card this would have to be devided by 2*/
+    if (block%2 == 0)                                        /*determine is the value was odd ('1' = upper halve) or even ('0' = lower halve)*/
+        offset = 0;                                            /*data in lower halve of 512byte block*/
+    else
+        offset = 256;                                        /*data in upper halve of 512byte block*/
+    block = block/2;                                        /*convert to a 512byte blocksize (this devides by two and truncates)*/
+    FileReadSector_X(&file, block);                            /*read a 512byte block from the medium*/
+    lp = 4;                                                    /*copy the data from source to destination*/
+    while (lp < 144)
+    {
+        DOS_buffer[4].buffer[lp-4] = block_buffer[offset+lp];
+        lp++;
+    }
+}
+
+/*this routine writes the BAM (as stored in the BAM_buffer (DOS_buffer[4].buffer[..]) back to the D64*/
+void D64WriteBAM(void)
+{
+    /*this routine only supports 35 track disks, since I lack the knowledge of 40 track size disks*/
+    unsigned char lp;    
+
+    D64BlockRead(18,0);                                        /*read the block holding the BAM information*/
+
+    lp = 0;                                                    /*alter the bytes holding the BAM info*/
+    while (lp < 140)
+    {
+        RAM_buffer[lp+4] = DOS_buffer[4].buffer[lp];        /*copy source to destination*/
+        lp++;
+    }
+
+    D64BlockWrite(18,0);                                    /*write the modified block*/
+}
+
+/*this routine request the free blocks per sector*/
+unsigned char D64ReadFreeBlocksPerTrack(unsigned char track)
+{
+    unsigned char bytepointer;
+
+    bytepointer = (track-1) << 2;                    /*multiply value by another 4*/
+    return(DOS_buffer[4].buffer[bytepointer]);        /*return with requested value*/
+}
+
+/*this routine request the free blocks per sector*/
+unsigned char D64WriteFreeBlocksPerTrack(unsigned char track, unsigned char value)
+{
+    unsigned char bytepointer;
+
+    bytepointer = (track-1) << 2;            /*multiply value by another 4*/
+    DOS_buffer[4].buffer[bytepointer] = value;
+    D64WriteBAM();                            /*write the modified BAM to the medium*/
+    return(TRUE);                            /*return with requested value*/
+}
+
+
+/*test the status of the corresponding block-flag, return True if set and False if cleared*/
+unsigned char D64BAMFlagTest(unsigned char track, unsigned char sector)
+{
+    unsigned char bytepointer, bitpointer, lp, mask;
+    
+    /*determine in which byte the required track/sector-flag (bit) is located*/
+    bytepointer = 1 + (4 * (track-1)) + (sector/8);
+    bitpointer = sector%8;
+        
+    mask = 0x01;                                        /*use a mask to alter the correct flag (bit)*/
+    for (lp=bitpointer; lp>0; lp--)
+    {
+        mask<<=1;            /*shift the byte one bit to the left*/
+    }
+
+    if ((DOS_buffer[4].buffer[bytepointer] & mask) == 0)
+        return(FALSE);
+    else
+        return(TRUE);    
+}
+
+/*this routine can set/clear (TRUE/FALSE) the appropriate flag of the sepcified track or sector*/
+void D64BAMFlagModify(unsigned char track, unsigned char sector, unsigned status)
+{
+    unsigned char bytepointer, bitpointer, lp, mask;
+    
+    /*determine in which byte the required track/sector-flag (bit) is located*/
+    bytepointer = 1 + (4 * (track-1)) + (sector/8);
+    bitpointer = sector%8;
+        
+    mask = 0xfe;                                        /*use a mask to alter the correct flag (bit)*/
+    for (lp=bitpointer; lp>0; lp--)
+    {
+        mask<<=1;            /*shift the byte one bit to the left*/
+        mask = mask + 1;    /*make the LSB 1, since the shift left inserts 0's*/
+    }
+
+    DOS_buffer[4].buffer[bytepointer] = DOS_buffer[4].buffer[bytepointer] & mask;
+    mask = 0xFF - mask;            /*invert the mask in order to use the mask to set the bit of the required flag*/
+    if (status == TRUE)            /*test if the flag needs to be set or cleared*/
+        DOS_buffer[4].buffer[bytepointer] =    DOS_buffer[4].buffer[bytepointer] | mask;
+}
+
+/*this routine will search for the first free block within the D64 according it's BAM, it returns the track and sector of that block*/
+unsigned char D64SeekFreeBlock(unsigned char *track, unsigned char *sector)
+{
+    /*this routine only supports 35 track disks, since I lack the knowledge of 40 track size disks*/
+    *track = 1;
+    *sector = 0;
+
+    while(!D64BAMFlagTest(*track, *sector))        /*scan the BAM for a free block*/
+    {
+        *sector = *sector + 1;
+        if (*sector == SPT[*track])
+        {
+            *sector = 0;
+            *track = * track + 1;
+            if (*track == 18)                    /*prevent writing in the directory track*/
+                *track = 19;                    /*so if we reach it... just skip it!!!*/
+        }
+        if (*track > 35)
+            return(FALSE);                        /*exit when all tracks are scanned*/
+    }
+    return(TRUE);                                /*exit with the track and sector of the first free block*/
+}
+
+/*this routine clear a flag that indicates that the corresponding track is set*/
+unsigned char D64BlockAllocate(unsigned char track, unsigned char sector)
+{
+    if (D64BAMFlagTest(track, sector) == TRUE)
+    {
+        D64BAMFlagModify(track, sector, 0);        /*clear the flag that indicates the specified track and sector*/
+        D64WriteBAM();                            /*write the modified BAM to the medium*/
+        return(TRUE);                            /*operation succesfully performed*/
+    }
+    else
+    {
+        return(FALSE);                            /*error:flag was allready cleared*/
+    }
+}
+
+/*this routine sets a flag that indicates that the corresponding track is free*/
+unsigned char D64BlockFree(unsigned char track, unsigned char sector)
+{
+    if (D64BAMFlagTest(track, sector) == FALSE)
+    {
+        D64BAMFlagModify(track, sector, 1);        /*set the flag that indicates the specified track and sector*/
+        D64WriteBAM();                            /*write the modified BAM to the medium*/
+        return(TRUE);                            /*operation succesfully performed*/
+    }
+    else
+    {
+        return(FALSE);                            /*error:flag was allready set*/
+    }
+}
+
+/*this routine reads a block of a req. track-sector of a D64 into the RAM_buffer*/
+void D64BlockRead(unsigned char track, unsigned char sector)
+{
+    unsigned int lp, block, offset;
+
+    block = D64ConvertTrackSectorToBlock(track, sector);    /*the block number is a 256byte blocksize, so for a card this would have to be devided by 2*/
+    if (block%2 == 0)                                        /*determine is the value was odd ('1' = upper halve) or even ('0' = lower halve)*/
+        offset = 0;                                            /*data in lower halve of 512byte block*/
+    else
+        offset = 256;                                        /*data in upper halve of 512byte block*/
+    block = block/2;                                        /*convert to a 512byte blocksize (this devides by two and truncates)*/
+    FileReadSector_X(&file, block);                            /*read a 512byte block from the medium*/
+    lp = 0;                                                    /*copy the data from source to destination*/
+    while (lp < 256)
+    {
+        RAM_buffer[lp] = block_buffer[offset+lp];
+        lp++;
+    }
+}
+
+/*this routine reads a block of a req. track-sector of a D64 into the RAM_buffer*/
+/*THIS IS THE FUTURE ROUTINE*/
+void D64BlockRead_new(unsigned char buffer, unsigned char track, unsigned char sector)
+{
+    unsigned int lp, block, offset;
+
+    block = D64ConvertTrackSectorToBlock(track, sector);    /*the block number is a 256byte blocksize, so for a card this would have to be devided by 2*/
+    if (block%2 == 0)                                        /*determine is the value was odd ('1' = upper halve) or even ('0' = lower halve)*/
+        offset = 0;                                            /*data in lower halve of 512byte block*/
+    else
+        offset = 256;                                        /*data in upper halve of 512byte block*/
+    block = block/2;                                        /*convert to a 512byte blocksize (this devides by two and truncates)*/
+    FileReadSector_X(&file, block);                            /*read a 512byte block from the medium*/
+    lp = 0;                                                    /*copy the data from source to destination*/
+    while (lp < 256)
+    {
+        DOS_buffer[buffer].buffer[lp] = block_buffer[offset+lp];    /*read (or to be precise) copy, the data from the media buffer to the DOS_buffer as specified by the user*/
+        lp++;
+    }
+}
+
+/*this routine write the contents of the RAM_buffer to the req. track-sector of the D64 file*/
+void D64BlockWrite(unsigned char track, unsigned char sector)
+{
+    unsigned int lp, block, offset;
+
+    block = D64ConvertTrackSectorToBlock(track, sector);    /*the block number is a 256byte blocksize, so for a card this would have to be devided by 2*/
+    if (block%2 == 0)                                        /*determine is the value was odd ('1' = upper halve) or even ('0' = lower halve)*/
+        offset = 0;                                            /*data in lower halve of 512byte block*/
+    else
+        offset = 256;                                        /*data in upper halve of 512byte block*/
+    block = block/2;                                        /*convert to a 512byte blocksize (this devides by two and truncates)*/
+    FileReadSector_X(&file, block);                            /*read a 512byte block from the medium*/
+    lp = 0;                                                    /*copy the data from source to temp destination*/
+    while (lp < 256)
+    {
+        block_buffer[offset+lp] = RAM_buffer[lp];
+        lp++;
+    }
+
+    FileWriteSector_X(&file, block);                        /*write the altered block back to the medium*/
+}
+
+/*this routine write the contents of the RAM_buffer to the req. track-sector of the D64 file*/
+/*this is the future routine*/
+void D64BlockWrite_new(unsigned char buffer, unsigned char track, unsigned char sector)
+{
+    unsigned int lp, block, offset;
+
+    block = D64ConvertTrackSectorToBlock(track, sector);    /*the block number is a 256byte blocksize, so for a card this would have to be devided by 2*/
+    if (block%2 == 0)                                        /*determine is the value was odd ('1' = upper halve) or even ('0' = lower halve)*/
+        offset = 0;                                            /*data in lower halve of 512byte block*/
+    else
+        offset = 256;                                        /*data in upper halve of 512byte block*/
+    block = block/2;                                        /*convert to a 512byte blocksize (this devides by two and truncates)*/
+    FileReadSector_X(&file, block);                            /*read a 512byte block from the medium*/
+    lp = 0;                                                    /*copy the data from source to temp destination*/
+    while (lp < 256)
+    {
+        block_buffer[offset+lp] = DOS_buffer[buffer].buffer[lp];
+        lp++;
+    }
+
+    FileWriteSector_X(&file, block);                        /*write the altered block back to the medium*/
+}
+
+/*This routine will search for the first dir entry within track 18, it returns the track and sector of the corresponding file*/
+/*mode: 0=first,1=next*/
+unsigned char D64SeekDirEntry(unsigned char mode, unsigned char *track, unsigned char *sector, unsigned char *entry_cnt)
+{
+    static unsigned char     entry_counter, CurrentDirTrack, CurrentDirSector, NextDirTrack, NextDirSector;
+    unsigned char            offset;
+
+    switch(mode)
+    {
+        case 0:    /*read from first directory block (Track 18, Sector 1)*/
+        {
+            NextDirTrack = 18;        
+            NextDirSector = 1;
+            entry_counter = 0;
+            break;
+        }
+
+        case 1:    // read from next directory block (Track/Sector)
+        {
+            entry_counter++;
+            if (entry_counter > 7)
+                entry_counter = 0;
+            break;
+        }
+    }
+
+    *entry_cnt = entry_counter;
+
+    if (entry_counter == 0)
+    {
+        if ((NextDirTrack == 0) && ((NextDirSector == 0) || (NextDirSector == 255)))    /*officially the only exit would be track=0 sector=255, but also track=0 sector=0 is very common to indicate the last block of an directory*/
+        {
+            return(FALSE);        /*end of directory allready reached*/
+        }
+        else
+        {
+            D64BlockRead(NextDirTrack, NextDirSector);
+            CurrentDirTrack =  NextDirTrack; 
+            CurrentDirSector = NextDirSector;
+            NextDirTrack = RAM_buffer[0];
+            NextDirSector = RAM_buffer[1];
+        }
+    }
+
+    *track = CurrentDirTrack;
+    *sector = CurrentDirSector;
+
+    offset = entry_counter * 32;                                /*each dir entry consists of 32bytes*/
+    dir_entry.filetype = RAM_buffer[offset+2];
+    dir_entry.track_first_block = RAM_buffer[offset+3];
+    dir_entry.sector_first_block = RAM_buffer[offset+4];
+    dir_entry.filename[0] = RAM_buffer[offset+5];
+    dir_entry.filename[1] = RAM_buffer[offset+6];
+    dir_entry.filename[2] = RAM_buffer[offset+7];
+    dir_entry.filename[3] = RAM_buffer[offset+8];
+    dir_entry.filename[4] = RAM_buffer[offset+9];
+    dir_entry.filename[5] = RAM_buffer[offset+10];
+    dir_entry.filename[6] = RAM_buffer[offset+11];
+    dir_entry.filename[7] = RAM_buffer[offset+12];
+    dir_entry.filename[8] = RAM_buffer[offset+13];
+    dir_entry.filename[9] = RAM_buffer[offset+14];
+    dir_entry.filename[10] = RAM_buffer[offset+15];
+    dir_entry.filename[11] = RAM_buffer[offset+16];
+    dir_entry.filename[12] = RAM_buffer[offset+17];
+    dir_entry.filename[13] = RAM_buffer[offset+18];
+    dir_entry.filename[14] = RAM_buffer[offset+19];
+    dir_entry.filename[15] = RAM_buffer[offset+20];
+    dir_entry.track_first_block_relfile = RAM_buffer[offset+21];
+    dir_entry.sector_first_block_relfile = RAM_buffer[offset+22];
+    dir_entry.record_size_relfile = RAM_buffer[offset+23];
+    dir_entry.unused_1[0] = RAM_buffer[offset+24];
+    dir_entry.unused_1[1] = RAM_buffer[offset+25];
+    dir_entry.unused_1[2] = RAM_buffer[offset+26];
+    dir_entry.unused_1[3] = RAM_buffer[offset+27];
+    dir_entry.track_first_block_replacementfile = RAM_buffer[offset+28];
+    dir_entry.sector_first_block_replacementfile = RAM_buffer[offset+29];
+    dir_entry.blocksize_low_byte = RAM_buffer[offset+30];
+    dir_entry.blocksize_high_byte = RAM_buffer[offset+31];    
+    dir_entry.unused_2[0] = RAM_buffer[offset+32];
+    dir_entry.unused_2[1] = RAM_buffer[offset+33];
+    
+    return(TRUE);        /*there is more info stored on other track(s)*/
+}
+
+/*this routine will seek for the next block within the specified file, the first/current block is indicated by track and sector and the next block is returned over the same pointer*/
+/*this routine is usefull for file DELETING/SCRATCHING and VALIDATING of files*/
+unsigned char D64SeekNextBlock(unsigned char *track, unsigned char *sector)
+{
+    D64BlockRead(*track, *sector);
+    *track = RAM_buffer[0];
+    *sector = RAM_buffer[1];
+
+    if (*track == 0)                /*track = 0 indicates the last sector of the file*/
+        return(FALSE);                /*end of file reached, no further blocks*/
+    else
+        return(TRUE);
+}
+
+/*this routine will add another entry inside the D64*/
+unsigned char D64AddDirEntry(unsigned char ftype, unsigned char tfblock, unsigned char sfblock, unsigned char *fname, unsigned int blocksize, unsigned char tfblock_rel, unsigned char sfblock_rel, unsigned char size_rel, unsigned char tfblock_replace, unsigned char sfblock_replace)
+{
+    unsigned char    lp, lp2, offset, result, entry_cnt, fbpt;
+    unsigned char    CurrentDirTrack, CurrentDirSector;
+    unsigned char    NextDirSector;
+
+    result = D64SeekDirEntry(0, &CurrentDirTrack, &CurrentDirSector, &entry_cnt);
+    while(1)
+    {    
+        if((result == TRUE) && (dir_entry.filetype == 0x00))
+        {
+            break;
+        }
+
+        if(result == FALSE)
+        {
+            NextDirSector = CurrentDirSector + 1;
+            if (NextDirSector > (SPT[CurrentDirTrack] -1))
+            {
+                return(FALSE);    /*directory is full*/
+            }
+            else
+            {
+                D64BlockRead(CurrentDirTrack,CurrentDirSector);                    /*read the directory block where we need to create our new entry*/
+                RAM_buffer[0] = CurrentDirTrack;                                /*update the next track field, since this was 0 indicating that this was the last dir sector, but now it is the second last*/
+                RAM_buffer[1] = NextDirSector;                                    /*update the next sector field*/
+                D64BlockWrite(CurrentDirTrack,CurrentDirSector);                /*update the new info to the card*/                
+                CurrentDirSector = NextDirSector;                                /*now we can state that the new t-s are the current one, since the pointer has been updated*/
+                D64BlockAllocate(CurrentDirTrack, CurrentDirSector);            /*claim the next block, update the BAM*/
+                fbpt = D64ReadFreeBlocksPerTrack(CurrentDirTrack) - 1;            /*decrement counter*/
+                D64WriteFreeBlocksPerTrack(CurrentDirTrack, fbpt);                 /*save new value to BAM*/
+                break;
+            }
+        }
+        result = D64SeekDirEntry(1, &CurrentDirTrack, &CurrentDirSector, &entry_cnt);
+    }
+    D64BlockRead(CurrentDirTrack,CurrentDirSector);                                /*read the (new) dir-block before we can alter it*/
+    offset = entry_cnt * 32;                                                    /*each dir entry consists of 32bytes*/
+
+    RAM_buffer[offset+2] = ftype;
+    RAM_buffer[offset+3] = tfblock;
+    RAM_buffer[offset+4] = sfblock;
+
+    /*derive the filename from the command string*/
+    lp = 0;
+    lp2 = 0;
+    while(lp<16)
+    {
+        if ((fname[lp2] !=0) && (fname[lp2] !=',') && (fname[lp2] !='='))    /*check for end of filename, if the string ends with 0 (null-byte, or if the string is separated by a ','-sign or if the string is separated by an '='-sign*/
+        {
+            RAM_buffer[offset+5+lp] = fname[lp2];
+            lp2++;
+        }
+        else
+        {
+            RAM_buffer[offset+5+lp] = 160;                    /*'padd' the filename with shifted spaces*/
+        }
+        lp++;
+    }    
+
+    RAM_buffer[offset+21] = tfblock_rel;
+    RAM_buffer[offset+22] = sfblock_rel;
+    RAM_buffer[offset+23] = size_rel;
+
+    RAM_buffer[offset+24] = 0x00;
+    RAM_buffer[offset+25] = 0x00;
+    RAM_buffer[offset+26] = 0x00;
+    RAM_buffer[offset+27] = 0x00;
+
+    RAM_buffer[offset+28] = tfblock_replace;
+    RAM_buffer[offset+29] = sfblock_replace;
+    RAM_buffer[offset+30] = blocksize%256;
+    RAM_buffer[offset+31] = blocksize/256;
+
+    RAM_buffer[offset+32] = 0x00;
+    RAM_buffer[offset+33] = 0x00;
+
+    D64BlockWrite(CurrentDirTrack,CurrentDirSector);
+    return(TRUE);
+}
+
+/*this routine will scratch (alias DELETE) a file entry. Actually, it sets the direntry to scratched and sets all blocks to free, the data is still present and can be retreived if not overwritten by another file*/
+unsigned char D64ScratchDirEntry(unsigned char dirtrack, unsigned char dirsector, unsigned char direntry)
+{
+    unsigned char offset, track, sector, fbpt;
+
+    offset = direntry * 32;                                    /*each dir entry consists of 32bytes*/
+    D64BlockRead(dirtrack, dirsector);                        /*load the directory block of interest*/
+    RAM_buffer[offset+2] = 0x00;                            /*make file of type "SCRatched"*/
+    D64BlockWrite(dirtrack, dirsector);                        /*save the (altered) block back*/
+    track = RAM_buffer[offset+3];                            /*track of the first block of the file that is to be deleted*/
+    sector =  RAM_buffer[offset+4];                            /*sector of the first block of the file that is to be deleted*/
+    D64BlockFree(track, sector);                            /*free the first block of the file in the BAM*/
+    fbpt = D64ReadFreeBlocksPerTrack(track) + 1;            /*increment the FreeBlockPerTrack counter*/
+    D64WriteFreeBlocksPerTrack(track, fbpt);                 /*save new value to BAM*/
+
+    while(D64SeekNextBlock(&track, &sector))
+    {
+        D64BlockFree(track, sector);                        /*free the ... block of the file in the BAM*/
+        fbpt = D64ReadFreeBlocksPerTrack(track) + 1;        /*increment the FreeBlockPerTrack counter*/
+        D64WriteFreeBlocksPerTrack(track, fbpt);             /*save new value to BAM*/
+    }
+    return(TRUE);
+}
+
+/*this routine will rename a directory entry*/
+/*the filename to be changed is specified by it's dirtrack, dirsector and entry number within the directory track*/
+/*the new filename is specified in filename*/
+unsigned char D64RenameDirEntry(unsigned char *fname, unsigned char dirtrack, unsigned char dirsector, unsigned char direntry)
+{
+    unsigned char offset, lp, lp2;
+
+    D64BlockRead(dirtrack, dirsector);                        /*read the block of interest*/
+
+    offset = direntry * 32;                                    /*each dir entry consists of 32bytes*/
+
+    /*derive the filename from the command string*/
+    lp = 0;
+    lp2 = 0;
+    while(lp<16)
+    {
+        if (fname[lp2] !=0)
+        {
+            RAM_buffer[offset+5+lp] = fname[lp2];
+            lp2++;
+        }
+        else
+        {
+            RAM_buffer[offset+5+lp] = 160;                    /*'padd' the filename with shifted spaces*/
+        }
+        lp++;
+    }    
+
+    D64BlockWrite(dirtrack, dirsector);                        /*write back the altered block*/
+    return(TRUE);
+}
+
+
+/*this routine will read one sector containing up to 8 filename entries from the D64 image directory*/
+/*mode: 0=first,1=next*/
+unsigned char D64LoadFileNameSector(unsigned char mode, unsigned char *dirtrack, unsigned char *dirsector)
+{
+    static unsigned char     NextDirTrack, NextDirSector;
+
+    switch(mode)
+    {
+        case 0:    /*read from first directory block (Track 18, Sector 1)*/
+        {
+            NextDirTrack = 18;        
+            NextDirSector = 1;
+            break;
+        }
+
+        case 1:    /*read from next directory block (Track , Sector )*/
+        {
+            if ((NextDirTrack == 0) && ((NextDirSector == 0) || (NextDirSector == 255)))    /*officially the only exit would be track=0 sector=255, but also track=0 sector=0 is very common to indicate the last block of an directory*/
+                return(FALSE);        /*end of directory allready reached*/
+            break;
+        }
+    }
+
+    *dirtrack = NextDirTrack;
+    *dirsector = NextDirSector;
+
+    D64LoadFile_X_Bytes(&file,NextDirTrack,NextDirSector,0,256);        /*location of next directory block*/        
+    NextDirTrack = block_buffer[0];
+    NextDirSector = block_buffer[1];
+    return(TRUE);        /*there is more info stored on other track(s)*/
+}
+
+
+/*this routine will read the D64 file and adds calculates the total number of free blocks within the D64-file*/
+unsigned int D64LoadFreeBlocks(void)
+{
+    unsigned int    FreeBlocks;
+    unsigned char    lp;
+
+    D64LoadFile_X_Bytes(&file,18,0,0,256);    /*directory block*/        
+    FreeBlocks = 0;
+    lp = 1;        
+    while(lp<=35)                        /*calculate the number of free blocks that can be used for actual user DATA using all 35 tracks stored in the BAM*/
+    {
+        if (lp != 18)                    /*exclude the DIRECTORY track, since this track can not store user DATA (it is used by the system)*/
+        {
+            FreeBlocks = FreeBlocks + block_buffer[4*lp];        /*the number of usable blocks is stored every 4 bytes*/
+        }
+        lp++;
+    }
+    return(FreeBlocks);
+}
+
+
+
+/*----------------------------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------------------------*/
+
+/*this routine will search (inside the D64) for a file that matches the given filename search pattern*/
+/*If found (TRUE), it return the Track and sector of the first block, as well as the blocksize of the file*/
+unsigned char D64SeekFile(unsigned char *filename, unsigned char *track, unsigned char *sector, unsigned int *blocksize, unsigned char *dirtrack, unsigned char *dirsector, unsigned char *direntry)
+{
+    unsigned char cnt, lp, offset, mode, dtrack, dsector;
+
+ error_code = 0;    /*unless we fail we will exit with no error*/
+    mode=0;    /*set sector read to first sector*/
+    while(D64LoadFileNameSector(mode, &dtrack, &dsector))        /*get directory filename sector*/
+    {
+        mode= 1;    /*set sector read to next sector*/
+        cnt = 0;    /*clear file index counter within this sector*/
+        while(cnt <8)
+        {
+            *dirtrack = dtrack;
+            *dirsector = dsector;
+            *direntry = cnt;
+            offset = 2 + cnt*32;                            /*calculate the offset for each entry within this sector*/
+            if ((block_buffer[offset+0] != 0x00) && (block_buffer[offset+0] != 0x80))    /*scratched files (0x00) are NOT displayed in the directory, and deleted files (0x80) cannot be opened*/    
+            {
+                *track = block_buffer[offset+1];                /*the first block with the data of this is stored in track/sector*/                
+                *sector = block_buffer[offset+2];
+                *blocksize = block_buffer[offset+28] + (256*(block_buffer[offset+29]));    /*calculate the size of this file (in blocks)*/            
+                lp = 2;            
+                do
+                {
+                //    OutputToRS232();                                /*set standard output to RS232*/
+                //    printf("\r\nblock_buffer[%d]=%c filename[%d]=%c",(offset+lp),block_buffer[offset+lp],(lp-3),filename[lp-3]);
+                //    OutputToLCD();                                    /*set standard output to LCD*/
+                    lp++; 
+                    if (lp == 19)        /*when we have reached all to the max number of chars there is no chr$(160)... but we do have a 100% match*/
+                        return(TRUE);    /*we have a 100% match*/
+
+                    if((filename[lp-3] == 0x0D) && (block_buffer[offset+lp] == 160))    /*test if this searchstring ends with a CarriageReturn if so then we DO have a 100% match*/
+                        return(TRUE);    /*we have a 100% match*/
+
+                    if((filename[lp-3] != 0) && (block_buffer[offset+lp] == 160))    /*when the search string has not been ended but the filename has... no match*/
+                        break;    /*we have no match*/
+
+                    if((filename[lp-3] == 0) && (block_buffer[offset+lp] != 160))    /*when the search string has been ended but the filename not... no match*/
+                        break;    /*we have no match*/
+
+                    if((filename[lp-3] == 0) && (block_buffer[offset+lp] == 160))    /*when we have reached all to the end of both strings... we have a 100% match*/
+                        return(TRUE);    /*we have a 100% match*/
+                    
+                    /*wildcard filter*/
+                    if (filename[lp-3] == '?')        /*when we encounter an '?', it does not matter what the real char of the filename is*/
+                        block_buffer[offset+lp] = '?';    /*therefore we can replace the real char by a '?' so that the comparison (at the end of this loop) can still be valid*/
+
+                    if (filename[lp-3] == '*')    /*when we have come so far and detected a * in our search string... we may consider this a match*/
+                        return(TRUE);    /*we have a partial or possible 100% match... but good enough to return with TRUE*/
+                }
+                while(block_buffer[offset+lp] == filename[lp-3]);    /*do the compare of current char of both strings*/
+            }
+            cnt++;
+        }
+    }
+
+    OutputToRS232();                                /*set standard output to RS232*/
+    printf("\r\nfile not found, exitting");
+    OutputToLCD();
+
+ error_code = 62;    /*FILE NOT FOUND*/
+    return(FALSE);        /*no match could be found*/
+}
+
+unsigned char D64LoadFile_X_Bytes(struct file2TYPE *file, unsigned char track, unsigned char sector, unsigned char byte, unsigned int NmbrOfBytes)
+{
+    unsigned long ByteAddress;
+
+    /*update the variable regarding the last accesses track and sector*/
+    LastTrack = track;        /*this values is required by the error-read routine*/
+    LastSector = sector;    /*this values is required by the error-read routine*/
+    
+    /*calculate the byte address determined by the D64-track-sector-byte numbers*/
+    ByteAddress = 0;
+    while(track--)
+    {
+        ByteAddress = ByteAddress + 256 * SPT[track];        /*retrieve number of sector per track from table and multiply the number of sectors with 256 (256bytes per sector), add this to the total*/
+    }
+    ByteAddress = ByteAddress + 256 * sector;
+    ByteAddress = ByteAddress + byte;
+
+    /*read the required data from the card located at the calculated address*/
+    FileRead_X_Bytes(file,ByteAddress,NmbrOfBytes);        
+
+    return(TRUE);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/D64_decoder.h	Mon Aug 22 05:48:51 2011 +0000
@@ -0,0 +1,69 @@
+#ifndef D64_DECODER_INCLUDED
+#define D64_DECODER_INCLUDED      
+
+/* Description of the error-bytes at the end of some .D64 files:
+
+    Code  Error  Type   1541 error description
+    ----  -----  ----   ------------------------------
+     01    00    N/A    No error, sector ok.
+     02    20    Read   Header block not found
+     03    21    Seek   No sync character
+     04    22    Read   Data block not present
+     05    23    Read   Checksum error in data block
+     06    24    Write  Write verify (on format)
+     07    25    Write  Write verify error
+     08    26    Write  Write protect on
+     09    27    Seek   Checksum error in header block
+     0A    28    Write  Write error
+     0B    29    Seek   Disk ID mismatch
+     0F    74    Read   Disk Not Ready (no device 1)
+*/
+
+struct    directory_entry
+{
+    unsigned char    filetype;
+    unsigned char    track_first_block;
+    unsigned char    sector_first_block;
+    unsigned char    filename[16];
+    unsigned char    track_first_block_relfile;
+    unsigned char    sector_first_block_relfile;
+    unsigned char    record_size_relfile;
+    unsigned char    unused_1[4];
+    unsigned char    track_first_block_replacementfile;
+    unsigned char    sector_first_block_replacementfile;
+    unsigned char    blocksize_low_byte;
+    unsigned char    blocksize_high_byte;    
+    unsigned char    unused_2[2];
+};
+
+
+/*routines*/
+/*--------*/
+void Clear_RAM_buffer(void);
+void D64ConvertBlockToTrackSector(unsigned int block, unsigned char *track, unsigned char *sector);
+unsigned int D64ConvertTrackSectorToBlock(unsigned char track, unsigned char sector);
+void D64ReadBAM(void);                                                                    /*this routine only supports 35 track disks, since I lack the knowledge of 40 track size disks*/
+void D64WriteBAM(void);                                                                    /*this routine only supports 35 track disks, since I lack the knowledge of 40 track size disks*/
+unsigned char D64ReadFreeBlocksPerTrack(unsigned char track);                            /*this routine only supports 35 track disks, since I lack the knowledge of 40 track size disks*/
+unsigned char D64WriteFreeBlocksPerTrack(unsigned char track, unsigned char value);        /*this routine only supports 35 track disks, since I lack the knowledge of 40 track size disks*/
+unsigned char D64BAMFlagTest(unsigned char track, unsigned char sector);                /*this routine only supports 35 track disks, since I lack the knowledge of 40 track size disks*/
+void D64BAMFlagModify(unsigned char track, unsigned char sector, unsigned status);
+unsigned char D64SeekFreeBlock(unsigned char *track, unsigned char *sector);            /*this routine only supports 35 track disks, since I lack the knowledge of 40 track size disks*/
+unsigned char D64BlockAllocate(unsigned char track, unsigned char sector);
+unsigned char D64BlockFree(unsigned char track, unsigned char sector);
+void D64BlockWrite(unsigned char track, unsigned char sector);
+void D64BlockWrite_new(unsigned char buffer, unsigned char track, unsigned char sector);
+void D64BlockRead(unsigned char track, unsigned char sector);
+void D64BlockRead_new(unsigned char buffer, unsigned char track, unsigned char sector);
+unsigned char D64SeekDirEntry(unsigned char mode, unsigned char *track, unsigned char *sector, unsigned char *entry_cnt);
+unsigned char D64SeekNextBlock(unsigned char *track, unsigned char *sector);
+unsigned char D64AddDirEntry(unsigned char ftype, unsigned char tfblock, unsigned char sfblock, unsigned char *fname, unsigned int blocksize, unsigned char tfblock_rel, unsigned char sfblock_rel, unsigned char size_rel, unsigned char tfblock_replace, unsigned char sfblock_replace);
+unsigned char D64ScratchDirEntry(unsigned char dirtrack, unsigned char dirsector, unsigned char direntry);
+unsigned char D64RenameDirEntry(unsigned char *fname, unsigned char dirtrack, unsigned char dirsector, unsigned char direntry);
+
+unsigned char D64LoadFileNameSector(unsigned char mode, unsigned char *dirtrack, unsigned char *dirsector);
+unsigned int D64LoadFreeBlocks(void);
+unsigned char D64LoadFile_X_Bytes(struct file2TYPE *file, unsigned char track, unsigned char sector, unsigned char byte, unsigned int NmbrOfBytes);
+unsigned char D64SeekFile(unsigned char *filename, unsigned char *track, unsigned char *sector, unsigned int *blocksize, unsigned char *dirtrack, unsigned char *dirsector, unsigned char *direntry);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/IEC_bus.c	Mon Aug 22 05:48:51 2011 +0000
@@ -0,0 +1,470 @@
+/*------------------------------------------------------------------------------------------*/
+/*This is the lowlevel IEC-bus_driver,                                                         */
+/*                                                                                            */
+/*Note that this driver is dirty because it polls the drive for it's flags. The             */
+/*routines in this driver should therefore only be called from a low priority task            */
+/*                                                                                          */
+/*Attention: routines tuned for 20MHz                                                       */
+/*------------------------------------------------------------------------------------------*/
+/*  History:                                                                        
+    --------      
+    2007-04-28    KeepItSimpleStupid, so hanging on to this live style I removed the 'filter' from the IEC_receive routine (it was unneccessary nonsense anyway)
+    2007-04-25    CheckForCommand had an delay of 200uS to ensure the "frame to release of ATN'-time" of min 20uS, this is removed and now in the higher level IEC staemachine (main.c)
+    2007-04-23    IECundoturnaround() was checking for the clok, this is not reuiqed in this situation, that's why the timeout worked bettre then no timeout, simply because the CLOCK check is not required at THIS stage of the communication
+    2007-04-16    removed a semicolon in the acknowledge timeout check... there should not be a semicolon after the while :-) (oops)
+    2007-04-15    ADDED a ATN check on IEC_turnaround routine
+    2007-04-09    removed all code that was made commentary with //
+    2007-04-08    added the same 'filter' on FreeIEC and CheckForCommand... and then disabled the new code with "//" simply because the new improvements made it even worse...
+    2007-04-07    added some extra checks to make sure we trigger/test the clock/data signals correctly (software signal filtering).
+                this is required because sometimes the device triggers incorrectly on signals meant for other devices on the bus
+                which is best noticable during intense bus trafic. But it is very likely to happen at any moment (you can't predict glitches/spikes).
+    2007-04-01    the check IEC_CLOCK == 1 in UNDOTURNAROUND now has a time-out, simply to improve reliablillity... it helps a lot!
+    2006-11-01    the channel value was always extracted from the commandbyte, even if there was no channel value. This caused problems in the new statemachine (before the new statemachine the channel was used before the 3f/5f command so this problme was no problem then)
+    2006-10-31    added thefunction IEC_monitor this function can be used to monitor bus activity without interfering
+                removed the setdeviceaddress function, since this is handled in MAIN.C
+    2006-10-30    the data and open command are identical when the errorchannel (15) is addressed
+    2006-10-22    changed the channel-variable to a variable outside the IEC_bus code, so it can be used in MAIN.c where it is declared
+    2006-10-20    added a function to set the timings of the IEC-bus (required for 25% faster VIC20-mode)
+    2006-07-03    changed 'FreeIEC' routine, this routine caused busylooping at an unwanted level, the busy-loop waiting for ATN going low 
+                is now located in main, so we can do other things while not communicating over the IEC-bus (manual file selection for instance)
+    2006-07-02    changed WaitForCommand into CheckForCommand, since the routine is no longer a while loop
+    2006-03-28    change in release and pulldown ATN-line routines, caused by new PCB design
+    2006-02-22    added frame_handshake signal for later use
+    2006-02-02    improvements in code layout... i.o.w. making it more readable                                                                  
+    2005-10-18    start of IEC bus driver
+    2005-10-19    further details on EOI condition
+    2005-10-22    delay routines for IEC timing
+    2005-10-25    corrected the IEC-receive routine (without EOI detection)
+    2005-10-26    timeouts and EOI handling
+    2005-10-27    bus turnaround routines and testing of write routines. Optimisation of the send routines
+    2006-01-04    added IEC_send_string, is much more convinient then printf
+    2006-01-10    TALK and LISTEN definitions were mixed up, is corrected. FreeIEC-routine added and improved
+    2006-01-13    adjusted delay in waitforcommand routine, now external devices work
+    2006-01-16    rewritten the waitforcommand routine
+*/
+
+/*  TO DO:                                                                          
+    ------      
+    - EOI acknowledge delay, set/test this to correct timings for 20MHz
+
+*/
+
+/*------------------------------------------------------------------------------------------*/
+
+/*--------------------------------------------------------*/
+/*                        includes                        */
+/*--------------------------------------------------------*/
+#include <mbed.h>
+
+#include <stdio.h>
+#include <IEC_bus.h>
+#include <delay.h>
+#include <hardware.h>
+
+/*--------------------------------------------------------*/
+/*                        constants                       */   
+/*--------------------------------------------------------*/
+#define    FALSE            0                            /*FALSE*/
+#define    TRUE            1                            /*TRUE*/
+
+/*--------------------------------------------------------*/
+/*                         globals                        */
+/*--------------------------------------------------------*/
+unsigned char            IEC_receive_delay;            /*set delay to ..uSec*/
+unsigned char            IEC_send_delay;                /*set delay to ..uSec*/
+
+/*external variables (variables also used in other .c files)*/
+/*external variables (variables also used in other .c files)*/
+extern bit                 EOI;                        /*End Of Indicator: this flag (when TRUE) indicates that the last byte is being transmitted or received*/
+extern bit                 TimeOut;                    /*Timeout-flag*/
+extern unsigned char    channel;                    /*this register holds the channel value*/
+
+/*--------------------------------------------------------*/
+/*                     local functions                    */
+/*--------------------------------------------------------*/
+
+
+/*--------------------------------------------------------*/
+/*                    external functions                  */
+/*--------------------------------------------------------*/
+
+//IEC_ATN : when IEC_ATN=0 it means that all devices must switch to listen (receive) mode immediatly
+
+
+/*set all IEC_signal lines in the correct mode*/
+void InitIEC(void)
+{
+    SetIEC_timings(TIMINGS_DEFAULT);    /*set timings according the default settings (C64 compatible mode)*/
+    IEC_ATN_REL();
+     IEC_CLOCK_REL();
+    IEC_DATA_REL();
+    EOI = FALSE;
+    TimeOut = FALSE;                
+}
+
+void SetIEC_timings(unsigned char settings)
+{
+    switch(settings)
+    {
+        case TIMINGS_VIC20:                /*Timings for VIC-20 mode*/
+        {                                /*-----------------------*/
+            IEC_receive_delay = 52;        /*set delay to ..uSec*/
+            IEC_send_delay = 60;        /*set delay to ..uSec*/
+            break;
+        }
+
+        case TIMINGS_DTV:                /*Timings for DTV (tuned IEC-bus speeds)*/
+        {                                /*--------------------------------------*/
+            IEC_receive_delay = 60;        /*set delay to ..uSec*/
+            IEC_send_delay = 80;        /*set delay to ..uSec*/
+            break;
+        }
+
+        default:                        /*Timings according (C64) IEC-specs*/
+        {                                /*---------------------------------*/
+            IEC_receive_delay = 70;        /*set delay to ..uSec*/
+            IEC_send_delay = 80;        /*set delay to ..uSec*/
+            break;
+        }        
+    }
+}
+
+/*free the IEC bus for use by other devices, the bus is free'd until ATN is released*/
+void FreeIEC(void)
+{
+    IEC_ATN_REL();
+     IEC_CLOCK_REL();
+    IEC_DATA_REL();
+    while(IEC_ATN() == 0);
+}
+
+
+/*this routine will wait untill it receives one byte over the IEC-bus*/
+unsigned char IEC_receive(unsigned char frame_handshake)
+{
+    unsigned char data;
+    unsigned char bitcount;
+    unsigned long t;
+
+    EOI = FALSE;                            /*clear the EOI flag*/
+    TimeOut = FALSE;                        /*clear the timeout flag*/
+    data = 0;                                /*clear destination register*/
+    bitcount = 8;                            /*the number of bits within a byte are still eight*/
+
+    /*-----Step1:Ready to send--------------------------------------------------------------------------------*/
+    while (IEC_CLOCK() == 0);                    /*wait (endlessly) until we see some action on the bus, we may respond whenever we please*/
+
+    /*Step2:Ready for data--------------------------------------------------------------------------------*/
+    IEC_DATA_REL();                        /*response to talker READY FOR DATA, this signal has no time-limit since we may be busy formatting a disk or printing out a chunk of text to paper*/
+
+    /*-----intermission:EOI--------------------------------------------------------------------------------*/
+    t = 5000;                        /*timeout value for detecting an EOI condition*/
+    while (IEC_CLOCK() == 1)            /*wait for the talker to indicate that the transmission will start (this signal must be received within 200uS, otherwise we may consider it as an EOI)*/
+    {
+        t--;                        /*when timed out, we have detected an EOI condition*/
+        if (t == 0)                    /*timeout detected ?*/
+        {
+            EOI = TRUE;                    /*set the EOI flag*/
+            IEC_DATA_PULL();        /*acknowledge the EOI condition*/
+            DelayBigUs(IEC_receive_delay);    /*delay for .. uSec*/
+            IEC_DATA_REL();            /*acknowledge the EOI condition*/
+        }
+    }
+
+    /*-----Step3:receiving the bits--------------------------------------------------------------------------------*/
+    while (bitcount != 0)            /*data is received with LSB first*/
+    {
+        data>>=1;                    /*shift the byte one bit to the right*/
+        bitcount--;                    /*decrement bitcounter by one*/
+        t = 5000;                    /*timeout value*/
+        while (IEC_CLOCK() == 0);        /*wait for the talker to release the clock line to signal "bit ready"*/
+        {
+            t--;                    /*timeout detection is required to prevent "hanging" in case of data transmission erros*/
+            if (t == 0)                /*timeout detected ?*/
+            {
+                TimeOut = TRUE;        /*set the timeout flag*/
+                return(0);            /*exit*/
+            }
+        }    
+
+        if (IEC_DATA() == 1)            /*test if bit is set or cleared (attention:documentation states that signals are inverted ?!?! error ?!?!*/
+            data = data + 128;        /*make bit 7 high*/
+
+        t = 5000;                    /*timeout value*/
+        while (IEC_CLOCK() == 1);        /*wait for the talker to pulldown the clock line*/
+        {
+            t--;                    /*timeout detection is required to prevent "hanging" in case of data transmission erros*/
+            if (t == 0)                /*timeout detected ?*/
+            {
+                TimeOut = TRUE;        /*set the timeout flag*/
+                return(0);            /*exit*/
+            }
+        }        
+    }
+
+    /*-----Step4:frame handshake--------------------------------------------------------------------------------*/
+    if (frame_handshake == FALSE)    /*we must acknowledge within 1 mS that we have received the data, if not the talker knows there is something wrong*/
+        DelayBigUs(1250);            /*delay for more then 1000 uSec*/        
+
+    IEC_DATA_PULL();            
+    return(data);                    /*exit with the received data*/
+}
+
+
+/*this routine will send one byte over the IEC-bus*/
+unsigned char IEC_send(unsigned char data)
+{
+    unsigned char bitcount;
+    unsigned long t;
+    bitcount = 8;                    /*the number of bits within a byte are still eight*/
+    TimeOut = FALSE;                /*clear the timeout flag*/
+
+    /*-----Step1:Ready to send--------------------------------------------------------------------------------*/
+
+    IEC_CLOCK_REL();            /*indicate to the listener that we are ready to send*/
+
+    /*-----Step2:Ready for data--------------------------------------------------------------------------------*/
+    while (IEC_DATA() == 0);            /*wait for the listener (computer) to release the data-line (ready to receive data), this may take forever... (according the IEC-bus definition)*/
+
+    /*intermission:EOI--------------------------------------------------------------------------------*/
+    if (EOI == TRUE)
+    {
+        DelayUs(200);                /*delay for more then 200 uSec*/
+        t = 5000;                    /*timeout value*/
+        while (IEC_DATA() == 1);        /*check for acknowledge of the EOI. The acknowledge is simply pulling the data-line down for a brief period*/
+        {
+            t--;                    /*timeout detection is required to prevent "hanging" in case of data transmission erros*/
+            if (t == 0)                /*timeout detected ?*/
+            {
+                TimeOut = TRUE;        /*set the timeout flag*/
+                return(FALSE);        /*exit*/
+            }
+        }
+        t = 5000;                    /*timeout value*/
+        while (IEC_DATA() == 0);        /**/
+        {
+            t--;                    /*timeout detection is required to prevent "hanging" in case of data transmission erros*/
+            if (t == 0)                /*timeout detected ?*/
+            {
+                TimeOut = TRUE;        /*set the timeout flag*/
+                return(FALSE);           /*exit*/
+            }
+        }
+        /*EOI is acknowledged by the listener (computer)*/
+    }
+    IEC_CLOCK_PULL();            /*indicate to the listener (computer) that the transmission will start*/
+    DelayUs(IEC_send_delay);            /*delay for .. uSec*/
+
+    /*-----Step3:receiving the bits--------------------------------------------------------------------------------*/
+    while (bitcount != 0)            /*data is transmitted with LSB first*/
+    {
+        IEC_CLOCK_PULL();        /*release the clockline in order to set the next bit on the data-line*/
+        DelayUs(IEC_send_delay);    /*delay for .. uSec*/
+        bitcount--;
+        if (data & 0x01)
+        {
+            IEC_DATA_REL();        
+        }
+        else
+        {        
+            IEC_DATA_PULL();            
+        }
+        IEC_CLOCK_REL();        /*indicate to the listener (computer) "bit ready"*/
+        data>>=1;                    /*shift the byte one bit to the right*/
+        DelayUs(IEC_send_delay);    /*delay for at least 60uSec when a C64 is listening*/
+    }
+    IEC_CLOCK_PULL();            /*the whole byte has been transmitted*/
+    DelayUs(IEC_send_delay);        /*delay for at least 60uSec when a C64 is listening*/
+    IEC_DATA_REL();                /*set clock and data in the correct order and wait for an acknowledge*/
+    DelayUs(25);                    /*wait a few uSec to prevent a false trigger*/
+    
+    /*----Step4:frame handshake--------------------------------------------------------------------------------*/
+    t = 5000;                        /*timeout value*/
+    while (IEC_DATA() == 1)            /*wait for the listener (computer) to acknowledge this byte it must respond within 1 mSec*/
+    {
+            t--;                    /*timeout detection is required to prevent "hanging" in case of data transmission erros*/
+            if (t == 0)                /*timeout detected ?*/
+            {
+                TimeOut = TRUE;        /*set the timeout flag*/
+                return(FALSE);        /*exit*/
+            }
+    }        
+    DelayUs(100);                    /*time between bytes is according IEC-specs at least 100 uSec*/
+    return(TRUE);                    /*the byte has been succesfully transmitted*/
+}
+
+
+/*this routine will wait untill it receives one byte over the IEC-bus*/
+/*this routine does NOT generate any signals, it only listens...     */
+unsigned char IEC_monitor(void)
+{
+    unsigned char data;
+    unsigned char bitcount;
+    unsigned long t;
+
+    EOI = FALSE;                    /*clear the EOI flag*/
+    TimeOut = FALSE;                /*clear the timeout flag*/
+    data = 0;                        /*clear destination register*/
+    bitcount = 8;                    /*the number of bits within a byte are still eight*/
+
+    /*-----Step1:Ready to send--------------------------------------------------------------------------------*/
+    while (IEC_CLOCK() == 0);            /*wait (endlessly) until we see some action on the bus, we may respond whenever we please*/
+
+    /*-----intermission:EOI--------------------------------------------------------------------------------*/
+    t = 5000;                        /*timeout value for detecting an EOI condition*/
+    while (IEC_CLOCK() == 1)            /*wait for the talker to indicate that the transmission will start (this signal must be received within 200uS, otherwise we may consider it as an EOI)*/
+    {
+        t--;                        /*when timed out, we have detected an EOI condition*/
+        if (t == 0)                    /*timeout detected ?*/
+            EOI = TRUE;                /*set the EOI flag*/
+    }
+
+    /*-----Step3:receiving the bits--------------------------------------------------------------------------------*/
+    while (bitcount != 0)            /*data is received with LSB first*/
+    {
+        data>>=1;                    /*shift the byte one bit to the right*/
+        bitcount--;                    /*decrement bitcounter by one*/
+        t = 5000;                    /*timeout value*/
+        while (IEC_CLOCK() == 0);        /*wait for the talker to release the clock line to signal "bit ready"*/
+        {
+            t--;                    /*timeout detection is required to prevent "hanging" in case of data transmission erros*/
+            if (t == 0)                /*timeout detected ?*/
+            {
+                TimeOut = TRUE;        /*set the timeout flag*/
+                return(0);            /*exit*/
+            }
+        }    
+
+        if (IEC_DATA() == 1)            /*test if bit is set or cleared (attention:documentation states that signals are inverted ?!?! error ?!?!*/
+            data = data + 128;        /*make bit 7 high*/
+
+        t = 5000;                    /*timeout value*/
+        while (IEC_CLOCK() == 1);        /*wait for the talker to pulldown the clock line*/
+        {
+            t--;                    /*timeout detection is required to prevent "hanging" in case of data transmission erros*/
+            if (t == 0)                /*timeout detected ?*/
+            {
+                TimeOut = TRUE;        /*set the timeout flag*/
+                return(0);            /*exit*/
+            }
+        }        
+    }
+    return(data);                    /*exit with the received data*/
+}
+
+
+/*this routine will handle strings, for sending strings over the IEC-bus*/
+void IEC_send_string(const unsigned char *inputstring)
+{
+    unsigned char lp;
+
+    lp = 0;
+    while(inputstring[lp] != 0)
+    {    
+        IEC_send(inputstring[lp]);
+        lp++;
+    }
+}
+
+void IEC_send_number_as_ASCII(unsigned char number)
+{
+    unsigned char i;
+
+    i = 0x30 + (number/10);            /*10's of the value*/
+    IEC_send(i);        
+    i = 0x30 + (number%10);            /*1's of the value*/
+    IEC_send(i);        
+}
+
+/*this routine will reverse the direction of the bus*/
+void IEC_turnaround(void)
+{
+    while (IEC_ATN() == 0);            /*wait (endlessly) until the computer releases ATN*/
+    while (IEC_CLOCK() == 0);            /*wait (endlessly) until the computer releases the clock line*/
+    IEC_DATA_REL();
+    DelayUs(25);                    /*small delay... to make the timing look like the timing of a real drive*/
+    IEC_CLOCK_PULL();
+    DelayUs(160);                    /*Tda = 80 uSec minimum acknowledge time for acknowledging the device is now a talker*/
+}
+
+
+/*this routine will set the direction on the bus back to normal (the way it was when the computer was switched on)*/
+void IEC_undoturnaround(void)
+{
+//    unsigned int timeout_cnt;
+//    DelayUs(50);                    /*Talk-Attention release (max. 100uS)*/
+    IEC_DATA_PULL();
+    IEC_CLOCK_REL();
+    DelayUs(25);                    /*small delay for .. uSec in order to prevent a false trigger*/
+//    timeout_cnt = 0;
+//    while (IEC_CLOCK() == 1)            /*wait until the computer pulls down the clock line or we timeout*/
+//    {
+//        if (timeout_cnt == 1000)
+//            break;                    /*timeout exceeded, leave routine*/
+//        else
+//            timeout_cnt++;
+//    }
+}
+
+/*this routine will let the bus lines go, as Jim Butterfield described, both talker and listener 'letgo'*/
+void IEC_letgo(void)
+{
+    DelayUs(50);                    /*after a suitable pause*/
+    IEC_DATA_REL();                /*dataline and clockline are released*/
+    IEC_CLOCK_REL();
+}
+
+extern DigitalOut(myled3);
+
+unsigned char CheckForCommand(unsigned char *outputcommand, unsigned char frame_handshake)
+{
+    if(IEC_ATN() == 1)                /* wait untill there is relevant info (a command is indicated by the attention signal) on the bus */
+    {
+        IEC_DATA_REL();            /*free the bus... (if not allready released)*/
+        return(FALSE);                /*no command received, yet...*/
+    }
+
+    IEC_DATA_PULL();            /*join the bus...*/
+    *outputcommand = IEC_receive(frame_handshake);    /*save the received command to a register specified by the caller of this routine*/
+    if ((TimeOut == FALSE) && (IEC_ATN() == 0))
+    {
+        if (*outputcommand == UNLISTEN)                /*check for command:UNLISTEN, device:..., Attention-line must still be active*/
+            return(UNLISTEN);
+    
+        if (*outputcommand == UNTALK)                /*check for command:UNTALK, device:..., Attention-line must still be active*/
+            return(UNTALK);
+
+        if ((*outputcommand & 0xF0) == DATA)        /*check for command:DATA, channel:..., Attention-line must still be active*/
+        {
+            channel = *outputcommand & 0x0F;                /*(if send) the channel is stored in the low-nibble of the command*/        
+            return(DATA);
+        }
+
+        if ((*outputcommand & 0xF0) == CLOSE)        /*check for command:CLOSE, channel:..., Attention-line must still be active*/
+        {
+            channel = *outputcommand & 0x0F;                /*(if send) the channel is stored in the low-nibble of the command*/        
+            return(CLOSE);
+        }
+
+        if ((*outputcommand & 0xF0) == OPEN)        /*check for command:OPEN, channel:..., Attention-line must still be active*/
+        {
+            channel = *outputcommand & 0x0F;                /*(if send) the channel is stored in the low-nibble of the command*/        
+            return(OPEN);
+        }
+
+        return(*outputcommand);                        /*when none of the above... it's for another device, return the entire command for further analasys*/
+    }
+    return(FALSE);                                    /*code should never reach this point!!!*/
+}
+
+
+/*--------------------------------------------------------*/
+/*                      local functions                   */
+/*--------------------------------------------------------*/
+
+
+
+
+/*
+The person who writes their sourcecode without comments is either very smart or very stupid
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/IEC_bus.h	Mon Aug 22 05:48:51 2011 +0000
@@ -0,0 +1,51 @@
+#ifndef IEC_BUS_INCLUDED
+#define IEC_BUS_INCLUDED      
+
+
+/*defines*/
+/*-------*/
+/*IEC commandset: the talker requests the addresses device to become a ...-er*/
+#define        LISTEN            0x20    /*base address, device 0-30*/
+#define        UNLISTEN        0x3F    /*base address, n/a*/                
+#define        TALK            0x40    /*base address, device 0-30*/        
+#define        UNTALK            0x5F    /*base address, n/a*/        
+#define        DATA            0x60    /*base address, secondary address 0-15 (this is in some documentation also refered to as OPEN_CHANNEL)*/
+#define        CLOSE            0xE0    /*base address, secondary address 0-15*/        
+#define        OPEN            0xF0    /*base address, secondary address 0-15*/        
+
+#define        TIMINGS_DEFAULT    10
+#define        TIMINGS_DTV        11
+#define        TIMINGS_VIC20    12
+extern int IEC_CLOCK();
+extern int IEC_DATA();
+extern int IEC_ATN();
+extern void IEC_ATN_REL();
+extern void IEC_ATN_PULL();
+extern void IEC_DATA_REL();
+extern void IEC_CLOCK_REL();
+extern void IEC_DATA_PULL();
+extern void IEC_CLOCK_PULL();
+
+/*routines*/
+/*--------*/
+void InitIEC(void);
+void SetIEC_timings(unsigned char settings);
+void FreeIEC(void);
+
+unsigned char IEC_receive(unsigned char frame_handshake);
+unsigned char IEC_send(unsigned char data);
+unsigned char IEC_monitor(void);
+void IEC_send_string(const unsigned char *inputstring);
+void IEC_send_number_as_ASCII(unsigned char number);
+void IEC_turnaround(void);
+void IEC_undoturnaround(void);
+void IEC_letgo(void);
+unsigned char CheckForCommand(unsigned char *outputcommand, unsigned char frame_handshake);
+
+#endif
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/T64_decoder.c	Mon Aug 22 05:48:51 2011 +0000
@@ -0,0 +1,87 @@
+/*----------------------------------------------------------------------------------*/
+/*    These routines are designed to decode a file according the D64 format           */
+/*----------------------------------------------------------------------------------*/
+/*                                                                                  */
+
+/*  History:                                                                        
+    -------- 
+    2008-02-17    started with T64 coding
+*/
+
+/*  TO DO:                                                                          
+    ------
+*/
+
+/*----------------------------------------------------------------------------------*/
+
+
+/*--------------------------------------------------------*/
+/*                        includes                        */
+/*--------------------------------------------------------*/
+#include <mbed.h>
+#include <stdio.h>
+#include <main.h>
+#include <hardware.h>
+#include <fat.h>
+#include <delay.h>
+#include <T64_decoder.h>
+
+/*--------------------------------------------------------*/
+/*                   (tunable) constants                  */ 
+/*--------------------------------------------------------*/
+
+
+/*--------------------------------------------------------*/
+/*                        constants                       */   
+/*--------------------------------------------------------*/
+#define            FALSE            0                /*FALSE*/
+#define            TRUE            1                /*TRUE*/
+
+/*--------------------------------------------------------*/
+/*                         table                          */
+/*--------------------------------------------------------*/
+
+/*variables*/
+extern struct            file2TYPE             file;            /*file handle*/
+
+extern unsigned char    error_code;                /*this holds the error-message generated by one of the disk routines*/
+
+/*--------------------------------------------------------*/
+/*                     local functions                    */
+/*--------------------------------------------------------*/
+
+/*************************************************************************************/
+/*External functions*/
+/*************************************************************************************/
+/*This routine will search for the first dir entry within track 18, it returns the track and sector of the corresponding file*/
+/*mode: 0=first,1=next*/
+unsigned char T64SeekDirEntry(unsigned char mode, unsigned char *track, unsigned char *sector, unsigned char *entry_cnt)
+{
+    static unsigned char     entry_counter, CurrentDirTrack, CurrentDirSector, NextDirTrack, NextDirSector;
+
+    switch(mode)
+    {
+        case 0:    /*read from first directory block (Track 18, Sector 1)*/
+        {
+            entry_counter = 0;
+            break;
+        }
+
+        case 1:    /*read from next directory block (Track , Sector )*/
+        {
+            entry_counter++;
+            break;
+        }
+    }
+
+    *entry_cnt = entry_counter;
+
+    
+    return(TRUE);        /*there is more info stored on other track(s)*/
+}
+
+
+
+/*----------------------------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------------------------*/
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/T64_decoder.h	Mon Aug 22 05:48:51 2011 +0000
@@ -0,0 +1,8 @@
+#ifndef T64_DECODER_INCLUDED
+#define T64_DECODER_INCLUDED      
+
+/*routines*/
+/*--------*/
+unsigned char T64SeekDirEntry(unsigned char mode, unsigned char *track, unsigned char *sector, unsigned char *entry_cnt);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ata.c	Mon Aug 22 05:48:51 2011 +0000
@@ -0,0 +1,612 @@
+/*------------------------------------------------------------------------------------------*/
+/*This is the lowlevel MMC/SD-card driver,                                                         */
+/*in order to function with the allready available software, the routines use the name ATA    */
+/*                                                                                            */
+/*Note that this driver is dirty because it polls the drive for it's flags. The             */
+/*routines in this driver should therefore only be called from a low priority task            */
+/*------------------------------------------------------------------------------------------*/
+
+/*    History:
+    2007-09-28    Minor layout changes
+    2006-08-25    Hurray, SanDisk wouldn't be SanDisk if they wouldn't have something different in the specifications that are to be considered as STANDARD !!! Why tell me why (as in the famous song of Anita Meijer)
+                The 'manual-rs-mms.pdf' version of 13-5-2004, page 5-12 states: CMD55 (SPI) This optional MMCA command is not supported in the SanDisk MultiMediaCard/RS-MultiMediaCard.
+                How are the big-boys able to work with these kind of standards what kind of info do they have that I don't have.
+                Well, it's up to me now to handle this exception... <zucht>
+    2006-08-24    all card now work EXCEPT the SanDisk RS-MMC, it even claims to be an SD-card... at least in my code, wonder why that is, back to the documentation
+    2006-08-23    Hurray, the card that first would not function is now functional !!!
+                COMPLETELY NUTS!!! Some MMC/SD-cards DO NOT, I repeat DO NOT function according specification,
+                normally after giving the command 'CMD17' the command responds with an error token (should be 0 when all is OK)
+                But for some reason some cards do not give this and simply answer 0xFF (instead of 0x00) this code is not even vaild according specs...
+                I do not get it, but when I simply ignore the expected response and immediatley start polling for the start-of-data then there is no problem what so ever...
+                Have they gone nuts or am I missing something... why is nobody following the protocol... this is RS232 connectors all over again.
+                For those who are not familiar whith RS232 connectors, some people still do not know the difference between
+                DTE and DCE and just mount a connector that fits to the device that is not meant to be connected in the way it is used. And wire the pins until it works and viola... no longer according specs, but it works in their own setup so it appears nothing is wrong, that is until you connect a device that is according specs...
+    2006-08-21    added more debugging info in order to find the problem regarding the problems with some card not being supported...
+                added a retry mechanism on the SDCARD_init() routine
+                renamed the routines SDCARD to CARD, this because it also handles MMC cards so the old name was incorrect
+    2006-02-02    improvements in code layout... i.o.w. making it more readable
+    2006-01-29    added first steps for byte addressable read routine (read X bytes)
+    2006-01-26    a routine waiting for 0xFE contained a ';' to much, so it did not timeout
+    2005-12-23    removal of the CS handling routines... not required for this project...
+    2005-12-11    (Dennis) added proper CS handling to enable sharing of SPI bus
+    2005-04-19    start of project
+*/
+
+
+/* TO DO:
+   ------
+    - improve 'AtaRead_X_Bytes'
+
+*/
+/*------------------------------------------------------------------------------------------*/
+
+/*--------------------------------------------------------*/
+/*                        includes                        */
+/*--------------------------------------------------------*/
+#include "mbed.h"
+
+//#include <stdio.h>
+#include "ata.h"
+#include "hardware.h"
+
+/*--------------------------------------------------------*/
+/*                        constants                       */   
+/*--------------------------------------------------------*/
+#define        FALSE        0            /*FALSE*/
+#define        TRUE        1            /*TRUE*/
+#define        MMCCARD        2
+#define        SDCARD        3
+
+/*MMC commandset*/
+#define        CMD0        0x40        /*Resets the multimedia card*/
+#define        CMD1        0x41        /*Activates the card's initialization process*/
+#define        CMD2        0x42        /*--*/
+#define        CMD3        0x43        /*--*/
+#define        CMD4        0x44        /*--*/
+#define        CMD5        0x45        /*reseved*/
+#define        CMD6        0x46        /*reserved*/
+#define        CMD7        0x47        /*--*/
+#define        CMD8        0x48        /*reserved*/
+#define        CMD9        0x49        /*CSD : Ask the selected card to send its card specific data*/
+#define        CMD10        0x4a        /*CID : Ask the selected card to send its card identification*/
+#define        CMD11        0x4b        /*--*/
+#define        CMD12        0x4c        /*STOP-command*/
+#define        CMD13        0x4d        /*Ask the selected card to send its status register*/
+#define        CMD14        0x4e        /*--*/
+#define        CMD15        0x4f        /*--*/
+#define        CMD16        0x50        /*Select a block length (in bytes) for all following block commands (Read:between 1-512 and Write:only 512)*/
+#define        CMD17        0x51        /*Reads a block of the size selected by the SET_BLOCKLEN command, the start address and block length must be set so that the data transferred will not cross a physical block boundry*/
+#define        CMD18        0x52        /*--*/
+#define        CMD19        0x53        /*reserved*/
+#define        CMD20        0x54        /*--*/
+#define        CMD21        0x55        /*reserved*/
+#define        CMD22        0x56        /*reserved*/
+#define        CMD23        0x57        /*reserved*/
+#define        CMD24        0x58        /*Writes a block of the size selected by CMD16, the start address must be alligned on a sector boundry, the block length is always 512 bytes*/
+#define        CMD25        0x59        /*--*/
+#define        CMD26        0x5a        /*--*/
+#define        CMD27        0x5b        /*Programming of the programmable bits of the CSD*/
+#define        CMD28        0x5c        /*If the card has write protection features, this command sets the write protection bit of the addressed group. The porperties of the write protection are coded in the card specific data (WP_GRP_SIZE)*/
+#define        CMD29        0x5d        /*If the card has write protection features, this command clears the write protection bit of the addressed group*/
+#define        CMD30        0x5e        /*If the card has write protection features, this command asks the card to send the status of the write protection bits. 32 write protection bits (representing 32 write protect groups starting at the specific address) followed by 16 CRD bits are transferred in a payload format via the data line*/
+#define        CMD31        0x5f        /*reserved*/
+#define        CMD32        0x60        /*sets the address of the first sector of the erase group*/
+#define        CMD33        0x61        /*Sets the address of the last sector in a cont. range within the selected erase group, or the address of a single sector to be selected for erase*/
+#define        CMD34        0x62        /*Removes on previously selected sector from the erase selection*/
+#define        CMD35        0x63        /*Sets the address of the first erase group within a range to be selected for erase*/
+#define        CMD36        0x64        /*Sets the address of the last erase group within a continuos range to be selected for erase*/
+#define        CMD37        0x65        /*Removes one previously selected erase group from the erase selection*/
+#define        CMD38        0x66        /*Erases all previously selected sectors*/
+#define        CMD39        0x67        /*--*/
+#define        CMD40        0x68        /*--*/
+#define        CMD41        0x69        /*reserved*/
+#define        CMD42        0x6a        /*reserved*/
+#define        CMD43        0x6b        /*reserved*/
+#define        CMD44        0x6c        /*reserved*/
+#define        CMD45        0x6d        /*reserved*/
+#define        CMD46        0x6e        /*reserved*/
+#define        CMD47        0x6f        /*reserved*/
+#define        CMD48        0x70        /*reserved*/
+#define        CMD49        0x71        /*reserved*/
+#define        CMD50        0x72        /*reserved*/
+#define        CMD51        0x73        /*reserved*/
+#define        CMD52        0x74        /*reserved*/
+#define        CMD53        0x75        /*reserved*/
+#define        CMD54        0x76        /*reserved*/
+#define        CMD55        0x77        /*reserved*/
+#define        CMD56        0x78        /*reserved*/
+#define        CMD57        0x79        /*reserved*/
+#define        CMD58        0x7a        /*reserved*/
+#define        CMD59        0x7b        /*Turns the CRC option ON or OFF. A '1' in the CRC option bit will turn the option ON, a '0' will turn it OFF*/
+#define        CMD60        0x7c        /*--*/
+#define        CMD61        0x7d        /*--*/
+#define        CMD62        0x7e        /*--*/
+#define        CMD63        0x7f        /*--*/
+
+/*--------------------------------------------------------*/
+/*                         globals                        */
+/*--------------------------------------------------------*/
+unsigned char crc_7;            /*contains CRC value*/
+unsigned char response_1;        /*byte that holds the first response byte*/
+unsigned char response_2;        /*byte that holds the second response byte*/
+unsigned char response_3;        /*byte that holds the third response byte*/
+unsigned char response_4;        /*byte that holds the fourth response byte*/
+unsigned char response_5;        /*byte that holds the fifth response byte*/
+
+/*--------------------------------------------------------*/
+/*                     local functions                    */
+/*--------------------------------------------------------*/
+void Command_R0(char cmd,unsigned short AdrH,unsigned short AdrL);
+void Command_R1(char cmd,unsigned short AdrH,unsigned short AdrL);
+void Command_R2(char cmd,unsigned short AdrH,unsigned short AdrL);
+void Command_R3(char cmd,unsigned short AdrH,unsigned short AdrL);
+void MmcAddCrc7(unsigned char c);
+void set_SPI_LowSpeed(void);
+void set_SPI_HighSpeed(void);
+unsigned char Card_CMD0(void);
+unsigned char Card_CMD1(void);
+unsigned char Card_BlockSize(void);
+unsigned char WaitForSOD(void);
+unsigned char Card_CID(void);
+unsigned char Card_CSD(void);
+
+/*************************************************************************************/
+/*************************************************************************************/
+/*External functions*/
+/*************************************************************************************/
+/*************************************************************************************/
+SPI spicard(p11, p12, p13); // mosi, miso, sclk
+DigitalOut SDCARD_CS(p14);
+extern Timer timeout;
+#define mySPI    spicard.write
+
+void set_SPI_LowSpeed(void)
+{
+    spicard.frequency(100000);  // low speed 100 kHz
+}
+
+void set_SPI_HighSpeed(void)
+{
+    spicard.frequency(1000000); // Set to 1MHz for data transfer
+}
+
+/*wait for start of data transfer with timeout*/
+unsigned char WaitForSOD(void)
+{
+
+    timeout.reset();
+    
+    while(mySPI(0xFF) != 0xFE)
+        if (timeout.read_us() >= 1000)                    
+        {
+            return(FALSE);
+        }
+    return(TRUE);
+}
+
+/*Enable the SDcard correctly*/
+unsigned char CARD_Init(void)
+{
+    unsigned short     lp;
+
+    set_SPI_LowSpeed();
+    SDCARD_CS=1;                                /*SDcard Disabled*/
+    for(lp=0;lp<10;lp++)                        /*Set SDcard in SPI-Mode, Reset*/
+        mySPI(0xFF);                                /*10 * 8bits = 80 clockpulses*/
+    SDCARD_CS=0;                                /*SDcard Enabled*/
+
+    wait_ms(50);
+//    for(lp=0;lp<50000;lp++);                    /*delay for a lot of milliseconds (at least 16 bus clock cycles)*/
+
+    if (Card_CMD0() == FALSE)
+        return(FALSE);                            /*error, quit routine*/
+
+    Command_R1(CMD55,0,0);                        /*when the response is 0x04 (illegal command), this must be an MMC-card*/
+    if (response_1 == 0x05)                        /*determine MMC or SD*/
+    {    /*An MMC-card has been detected, handle accordingly*/
+        /*-------------------------------------------------*/
+        if (Card_CMD1() == FALSE)
+            return(FALSE);                        /*error, quit routine*/
+    }
+    else
+    {    /*An SD-card has been detected, handle accordingly*/
+        /*-------------------------------------------------*/
+        timeout.reset();
+        response_1 = 1;
+        while(response_1 != 0)
+        {
+            Command_R1(CMD41,0,0);
+            Command_R1(CMD55,0,0);
+            if (timeout.read_us() > 10000)                /*timeout mechanism*/
+            {
+                return(FALSE);                    /*error, quit routine*/
+            }
+        }
+    }
+
+    if (Card_BlockSize() == FALSE)
+        return(FALSE);                            /*error, quit routine*/
+
+    set_SPI_HighSpeed();
+    return(TRUE);                    
+}
+
+/*Enable the SDcard according SanDisk RS-MMC (a.k.a. the idiots not follow the world's standards*/
+unsigned char CARD_AlternativeInit(void)
+{
+    unsigned short     lp;
+
+    set_SPI_LowSpeed();
+    SDCARD_CS=1;                                /*SDcard Disabled*/
+    for(lp=0; lp < 10; lp++)                    /*Set SDcard in SPI-Mode, Reset*/
+        mySPI(0xFF);                                /*10 * 8bits = 80 clockpulses*/
+    SDCARD_CS=0;                                /*SDcard Enabled*/
+
+    wait_ms(50);
+    // for(lp=0; lp < 50000; lp++);                /*delay for a lot of milliseconds (at least 16 bus clock cycles)*/
+
+    if (Card_CMD0() == FALSE)
+        return(FALSE);                            /*error, quit routine*/
+
+    if (Card_CMD1() == FALSE)
+        return(FALSE);                            /*error, quit routine*/
+
+    if (Card_BlockSize() == FALSE)
+        return(FALSE);                            /*error, quit routine*/
+
+    set_SPI_HighSpeed();
+    return(TRUE);                    
+}
+
+
+unsigned char Card_BlockSize(void)
+{
+    unsigned char    retry_counter;
+
+    retry_counter = 100;                        /*this routine is verrrrrrrry important, and sometimes fails on some cards so a retry mechanism is crucial*/
+    while(retry_counter--)
+    {
+        Command_R1(CMD16,0,512);                /*Set read block length to 512 bytes, by the way 512 is default, but since nobody if following standards...*/
+        if (response_1 == 0)
+            break;
+
+        if (retry_counter == 0)
+            return(FALSE);
+    }
+    return(TRUE);
+}
+
+unsigned char Card_CID(void)
+{
+    Command_R1(CMD10,0,0);                        /*read CID register (total of 16Bytes)*/
+//    if (response_1 !=0)
+//    {
+//        return(ERROR_CARDINIT_CID);                /*exit if invalid response*/
+//    }
+    if (WaitForSOD() == FALSE)                    /*wait for start-of-data (function features time-out)*/
+        return(FALSE);
+
+    OutputToRS232();                            /*set standard output to RS232*/
+    printf("\r\n\r\nCID registers (16bytes)\r\n-----------------------");
+    printf("\r\nCID(01) [manuf-ID] = %02X",(mySPI(0xFF)));    /*manuf-ID, 3 bytes*/
+    printf("\r\nCID(02) [manuf-ID] = %02X",(mySPI(0xFF)));    /*manuf-ID, 3 bytes*/
+    printf("\r\nCID(03) [manuf-ID] = %02X",(mySPI(0xFF)));    /*manuf-ID, 3 bytes*/
+    printf("\r\nCID(04) [prodname] = %02X",(mySPI(0xFF)));    /*productname, 7 bytes*/                    
+    printf("\r\nCID(05) [prodname] = %02X",(mySPI(0xFF)));    /*productname, 7 bytes*/                    
+    printf("\r\nCID(06) [prodname] = %02X",(mySPI(0xFF)));    /*productname, 7 bytes*/                    
+    printf("\r\nCID(07) [prodname] = %02X",(mySPI(0xFF)));    /*productname, 7 bytes*/                    
+    printf("\r\nCID(08) [prodname] = %02X",(mySPI(0xFF)));    /*productname, 7 bytes*/                    
+    printf("\r\nCID(09) [prodname] = %02X",(mySPI(0xFF)));    /*productname, 7 bytes*/                    
+    printf("\r\nCID(10) [prodname] = %02X",(mySPI(0xFF)));    /*productname, 7 bytes*/
+    printf("\r\nCID(11) [0x HW,FW] = %02X",(mySPI(0xFF)));    /*revision, hi-nibble=HW, low-nibble=FW, 1 byte*/
+    printf("\r\nCID(12) [serial #] = %02X",(mySPI(0xFF)));    /*serial number, 3 bytes*/
+    printf("\r\nCID(13) [serial #] = %02X",(mySPI(0xFF)));    /*serial number, 3 bytes*/
+    printf("\r\nCID(14) [serial #] = %02X",(mySPI(0xFF)));    /*serial number, 3 bytes*/
+    printf("\r\nCID(15) [0x Mo,Ye] = %02X",(mySPI(0xFF)));    /*revision, hi-nibble=Month, low-nibble=Year, 1 byte*/
+    printf("\r\nCID(16) [7-1 =CRC] = %02X",(mySPI(0xFF)));    /*7-1=CRC checksum, 0=not used, 1 byte*/
+    OutputToLCD();                                /*set standard output to LCD*/
+    return(TRUE);
+}
+
+unsigned char Card_CSD(void)
+{
+    unsigned short     lp;
+
+    Command_R1(CMD9,0,0);                        /*read CSD register*/
+//    if (response_1 !=0)
+//    {
+//        return(ERROR_CARDINIT_CSD);                /*exit if invalid response*/
+//    }
+    if (WaitForSOD() == FALSE)                    /*wait for start-of-data (function features time-out)*/
+        return(FALSE);
+
+    OutputToRS232();                            /*set standard output to RS232*/
+    printf("\r\n\r\nCSD registers (16bytes)\r\n-----------------------");
+    for(lp=0; lp < 17; lp++)                    
+    {
+        printf("\r\nCSD(%02d) = %02X",lp,(mySPI(0xFF)));
+    }
+    OutputToLCD();                                /*set standard output to LCD*/
+    return(TRUE);
+}
+
+
+/*request the status register of the card*/
+unsigned char CARD_Status(unsigned char *ResponseData)
+{
+    Command_R2(CMD13,0,0);
+    ResponseData[1] = response_1;                /*return the first response byte (---) in reg[1]*/
+    ResponseData[0] = response_2;                /*return the second  response byte (LSB) in reg[0]*/
+    return(TRUE);
+}
+
+
+/*Request the OCR register (SD-card in SPI-mode that is to be done with CMD58), this will give us the operation condition sof the card*/    
+unsigned char CARD_OperatingConditions(unsigned char *ResponseData)
+{
+    timeout.reset();
+    response_1 = 1;
+    while(response_1 != 0)
+    {
+        Command_R3(CMD58,0,0);
+        if (timeout.read_us()>255)                        /*timeout mechanism*/
+        {
+            return(FALSE);
+        }
+    }
+
+    ResponseData[3] = response_2;                /*return the second response byte (MSB) in reg[3]*/
+    ResponseData[2] = response_3;                /*return the third  response byte (---) in reg[2]*/
+    ResponseData[1] = response_4;                /*return the fourth response byte (---) in reg[1]*/
+    ResponseData[0] = response_5;                /*return the fifth  response byte (LSB) in reg[0]*/
+    return(TRUE);
+}
+
+
+/*Read XXX bytes from the card*/
+/*In some suitations it is not relevant to read the entire sector,*/
+/*Sometimes only one byte is required, then this routine comes in handy...*/
+unsigned char AtaRead_X_Bytes(unsigned long lba, unsigned int offset, unsigned char *ReadData, unsigned int NmbrOfBytes)
+{
+    unsigned long lp;
+    unsigned short upper_lba, lower_lba;
+    unsigned char *p,c;
+    
+    lba = lba * 512;                                /*calculate byte address*/
+    upper_lba = (lba/65536);
+    lower_lba = (lba%65536);
+
+    Command_R1(CMD17, upper_lba, lower_lba);        /*read block start at ...,...*/
+//    if (response_1 !=0)                                /*usually you would check the response, BUT not all do this, don't ask me why, but all cards eventually come with the 0xFE (start of data)*/
+//        return(FALSE);                                /*exit if invalid response*/
+    
+    if (WaitForSOD() == FALSE)                        /*wait for start-of-data (function features time-out)*/
+        return(FALSE);
+
+//    /*read data and exit OK*/
+//    p=ReadData;
+//    do
+//    {
+//        SSPBUF = 0xff;
+//        while (!BF);        
+//        *(p++)= SSPBUF;    
+//    }
+//    while(--NmbrOfBytes);
+//
+//    Command_R1(CMD12, 0xff, 0xff);        /*send the stop command*/
+//    return(TRUE);
+
+    p=ReadData;
+    for(lp=0; lp < 512; lp++)                    
+    {
+        c=mySPI(0xff);
+        if(offset == 0)                /*skip the inrelevant bytes*/
+            *(p++)=c;    
+        else
+        {
+            *(p)=c;                
+            offset--;
+        }
+    }
+
+    mySPI(0xff);
+    mySPI(0xff);
+    return(TRUE);
+}
+
+
+/*Read single block (with block-size set by CMD16 to 512 by default)*/
+unsigned char AtaReadSector(unsigned long lba, unsigned char *ReadData)
+{
+    unsigned short     upper_lba, lower_lba;
+    unsigned char     i;        
+    unsigned char     *p;
+    
+
+    lba = lba * 512;                                            /*calculate byte address*/
+    upper_lba = (lba/65536);
+    lower_lba = (lba%65536);
+    /*printf("\r\nlba=%ld, upper lba=%d, lower lba=%d",lba, upper_lba,lower_lba);*/
+
+    Command_R1(CMD17, upper_lba, lower_lba);                    /*read block start at ...,...*/
+//    if (response_1 !=0)
+//    {
+//        return(ERROR_ATAREAD_CMD17);                            /*exit if invalid response*/
+//    }
+    
+    if (WaitForSOD() == FALSE)                                    /*wait for start-of-data (function features time-out)*/
+        return(ERROR_ATAREAD_TIMEOUT);
+
+    /*read data and exit OK*/
+    p=ReadData;
+    i=0;
+    do
+    {
+        *(p++)=mySPI(0xff);
+    }
+    while(--i);
+
+    do
+    {
+        *(p++)=mySPI(0xff);            
+    }
+    while(--i);
+    //for(lp=0; lp < 512; lp++)                    
+    //    ReadData[lp] = mySPI(0xFF);
+
+    mySPI(0xff);
+    mySPI(0xff);
+    return(TRUE);
+}
+    
+
+
+/*Write: 512 Byte-Mode, this will only work (read MMC and SD-card specs) with a sector/block size of 512*/
+unsigned char AtaWriteSector(unsigned long lba, unsigned char *WriteData)
+{
+    unsigned short upper_lba, lower_lba, lp;    /*Variable 0...65535*/
+    unsigned char i;
+
+    lba = lba * 512;                            /*since the MMC and SD cards are byte addressable and the FAT relies on a sector address (where a sector is 512bytes big), we must multiply by 512 in order to get the byte address*/
+    upper_lba = (lba/65536);
+    lower_lba = (lba%65536);
+
+    Command_R1(CMD24, upper_lba, lower_lba);
+    if (response_1 != 0)
+    {
+        return(FALSE);
+    }
+    else
+    {
+        SDCARD_CS=0;            /*SDcard Enabled*/
+        mySPI(0xFF);
+        mySPI(0xFF);
+        mySPI(0xFE);
+
+        for(lp=0; lp < 512; lp++)
+            {
+                mySPI(WriteData[lp]);
+            }
+        mySPI(255);                        // Send 2 Byte's without a meaning... although required by protocol
+        mySPI(255);
+
+        i = mySPI(0xFF);
+//        i &=0b.0001.1111;
+//        if (i != 0b.0000.0101) 
+//            printf("Write error\n\r");
+//        else
+//            printf("Write succeeded?");
+        while(mySPI(0xFF) !=0xFF);        /*wait until the card has finished writing the data*/
+        return(TRUE);
+    }
+}
+ 
+
+/*************************************************************************************/
+/*Internal functions*/
+/*************************************************************************************/
+
+unsigned char Card_CMD0(void)
+{
+    unsigned char    retry_counter;
+
+    retry_counter = 100;                        /*this routine is verrrrrrrry important, and sometimes fails on some cards so a retry mechanism is crucial*/
+    while(retry_counter--)
+    {
+        Command_R1(CMD0,0,0);                    /*CMD0: Reset all cards to IDLE state*/
+        if (response_1 == 1)
+            break;
+
+        if (retry_counter == 0)
+            return(FALSE);                        /*error, quit routine*/
+    }
+    return(TRUE);
+}
+
+unsigned char Card_CMD1(void)
+{
+    timeout.reset();
+    response_1 = 1;
+    while(response_1 != 0)
+    {
+        Command_R1(CMD1,0,0);                /*activate the cards init process*/    
+        if (timeout.read_us() > 10000)                /*timeout mechanism*/
+        {
+            return(FALSE);
+        }
+    }
+    return(TRUE);
+}
+
+
+/*Send a command to the SDcard*/
+void Command_R0(char cmd,unsigned short AdrH,unsigned short AdrL)
+{
+    crc_7=0;
+    mySPI(0xFF);                /*flush SPI-bus*/
+
+    mySPI(cmd);
+    MmcAddCrc7(cmd);        /*update CRC*/
+    mySPI(AdrH/256);            /*use upper 8 bits (everything behind the comma is discarded)*/
+    MmcAddCrc7(AdrH/256);    /*update CRC*/
+    mySPI(AdrH%256);            /*use lower 8 bits (shows the remaining part of the devision)*/
+    MmcAddCrc7(AdrH%256);    /*update CRC*/
+    mySPI(AdrL/256);            /*use upper 8 bits (everything behind the comma is discarded)*/
+    MmcAddCrc7(AdrL/256);    /*update CRC*/
+    mySPI(AdrL%256);            /*use lower 8 bits (shows the remaining part of the devision)*/
+    MmcAddCrc7(AdrL%256);    /*update CRC*/
+
+    crc_7<<=1;                /*shift all bits 1 position to the left, to free position 0*/
+    crc_7++;                /*set LSB to '1'*/
+
+    mySPI(crc_7);                /*transmit CRC*/
+    mySPI(0xFF);                /*flush SPI-bus, or int other words process command*/
+}
+
+
+/*Send a command to the SDcard, a one byte response is expected*/
+void Command_R1(char cmd,unsigned short AdrH,unsigned short AdrL)
+{
+    Command_R0(cmd, AdrH, AdrL);    /*send command*/
+    response_1 = mySPI(0xFF);            /*return the reponse in the correct register*/
+}
+
+
+/*Send a command to the SDcard, a two byte response is expected*/
+void Command_R2(char cmd,unsigned short AdrH,unsigned short AdrL)
+{
+    Command_R0(cmd, AdrH, AdrL);    /*send command*/
+    response_1 = mySPI(0xFF);            /*return the reponse in the correct register*/
+    response_2 = mySPI(0xFF);            
+}
+
+
+/*Send a command to the SDcard, a five byte response is expected*/
+void Command_R3(char cmd,unsigned short AdrH,unsigned short AdrL)
+{
+    Command_R0(cmd, AdrH, AdrL);    /*send command*/
+    response_1 = mySPI(0xFF);            /*return the reponse in the correct register*/
+    response_2 = mySPI(0xFF);            
+    response_3 = mySPI(0xFF);            
+    response_4 = mySPI(0xFF);            
+    response_5 = mySPI(0xFF);            
+}
+
+
+/*calculate CRC7 checksum*/
+void MmcAddCrc7(unsigned char c)
+{
+    unsigned char i;
+    
+    i=8;
+    do
+    {
+        crc_7<<=1;
+        if(c&0x80)
+            crc_7^=0x09;
+        if(crc_7&0x80)
+            crc_7^=0x09;
+        c<<=1;
+    }
+    while(--i);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ata.h	Mon Aug 22 05:48:51 2011 +0000
@@ -0,0 +1,15 @@
+#ifndef _ATA_H_INCLUDED
+#define _ATA_H_INCLUDED
+
+unsigned char CARD_Init(void);
+unsigned char CARD_AlternativeInit(void);
+unsigned char CARD_Status(unsigned char *ResponseData);
+unsigned char CARD_OperatingConditions(unsigned char *ResponseData);
+unsigned char AtaRead_X_Bytes(unsigned long lba, unsigned int offset, unsigned char *ReadData, unsigned int NmbrOfBytes);
+unsigned char AtaReadSector(unsigned long lba, unsigned char *ReadData);
+unsigned char AtaWriteSector(unsigned long lba, unsigned char *WriteData);
+
+#define        ERROR_ATAREAD_CMD17                20
+#define        ERROR_ATAREAD_TIMEOUT            21
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/delay.c	Mon Aug 22 05:48:51 2011 +0000
@@ -0,0 +1,110 @@
+/*----------------------------------------------------------------------------------*/
+/*
+high level delay routines - see delay.h for more info.
+
+Designed by Shane Tolmie of KeyGhost corporation.  Freely distributable.
+Questions and comments to shane@keyghost.com
+PICuWEB - Program PIC micros with C. Site has FAQ and sample source code. http://www.workingtex.com/htpic
+
+For Microchip PIC18xxxxx and Hi-Tech C
+
+*/
+/*----------------------------------------------------------------------------------*/
+
+/*  History:                                                                        
+    -------- 
+    2006-02-02        -improvements in code layout... i.o.w. making it more readable                                                                       
+
+*/
+
+/*  TO DO:                                                                          
+    ------      
+*/
+
+/*----------------------------------------------------------------------------------*/
+
+#ifndef __DELAY_C
+#define __DELAY_C
+
+/*--------------------------------------------------------*/
+/*                        includes                        */
+/*--------------------------------------------------------*/
+#include <mbed.h>
+#include <delay.h>
+#include <main.h>
+
+/*--------------------------------------------------------*/
+/*                         globals                        */
+/*--------------------------------------------------------*/
+unsigned char delayus_variable;
+
+void CLRWDT(){};
+
+/*****************************************************************************************************************/
+/*****************************************************************************************************************/
+
+void DelayBigUs(unsigned int cnt)
+{
+    unsigned char    i;
+
+    i = (unsigned char)(cnt>>8);
+    while(i>=1)
+    {
+        i--;
+        DelayUs(253);
+        CLRWDT();
+    }
+    DelayUs((unsigned char)(cnt & 0xFF));
+}
+
+void DelayMs(unsigned char cnt)
+{
+    unsigned char    i;
+    do {
+        i = 4;
+        do {
+            DelayUs(250);
+            CLRWDT();
+        } while(--i);
+    } while(--cnt);
+}
+
+//this copy is for the interrupt function
+void DelayMs_interrupt(unsigned char cnt)
+{
+    unsigned char    i;
+    do {
+        i = 4;
+        do {
+            DelayUs(250);
+        } while(--i);
+    } while(--cnt);
+}
+
+void DelayBigMs(unsigned int cnt)
+{
+    unsigned char    i;
+    do {
+        i = 4;
+        do {
+            DelayUs(250);
+            CLRWDT();
+        } while(--i);
+    } while(--cnt);
+}
+
+void DelayS(unsigned char cnt)
+{
+    unsigned char i;
+    do {
+        i = 4;
+        do {
+            DelayMs(250);
+            CLRWDT();
+        } while(--i);
+    } while(--cnt);
+}
+
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/delay.h	Mon Aug 22 05:48:51 2011 +0000
@@ -0,0 +1,92 @@
+/*For Microchip 18Fxxx or 18Cxxx and Hi-Tech C
+
+Designed by Shane Tolmie of www.microchipC.com corporation.  Freely distributable.
+Questions and comments to webmaster@microchipC.com.
+Lots of Hi-Tech C FAQ and sample source code at http://www.microchipC.com/.
+
+Example C:
+
+#define PIC_CLK 4000000
+
+unsigned int timeout_int, timeout_char;
+
+DelayUs(40);  //do NOT do DelayUs(N) of N<5 @ 4Mhz or else it executes DelayUs(255) !!!!
+DelayUs(255); //max
+
+dly250n;      //delay 250ns
+dly1u;        //delay 1us
+
+timeout_char=timeout_char_us(1147);
+while(timeout_char-- && (RA1==0));  //wait up to 1147us for port RA1 to go high
+                    //  - this is the max timeout
+
+timeout_int=timeout_int_us(491512);
+while(timeout_int-- && (RA1==0));   //wait up to 491512us for port RA1 to go high
+                    //  - this is the max timeout
+
+*/
+
+#ifndef __DELAY_H
+#define __DELAY_H
+
+
+extern unsigned char delayus_variable;
+
+#define DelayUs wait_us
+
+/*
+
+timeouts:
+
+C code for testing with ints:
+
+            unsigned int timeout;
+            timeout=4000;
+            PORT_DIRECTION=OUTPUT;
+            while(1)
+            {
+                PORT=1;
+                timeout=8000;
+                while(timeout-- >= 1);    //60ms @ 8Mhz, opt on, 72ms @ 8Mhz, opt off
+                PORT=0;
+            }
+
+Time taken:    optimisations on:        16cyc/number loop, 8us @ 8Mhz
+            optimisations off:        18cyc/number loop, 9us @ 8Mhz
+            with extra check ie:    && (RB7==1), +3cyc/number loop, +1.5us @ 8Mhz
+
+C code for testing with chars:
+
+            similar to above
+
+Time taken:    optimisations on:        9cyc/number loop, 4.5us @ 8Mhz
+            with extra check ie:    && (RB7==1), +3cyc/number loop, +1.5us @ 8Mhz
+
+Formula:    rough timeout value = (<us desired>/<cycles per loop>) * (PIC_CLK/4.0)
+
+To use:        //for max  timeout of 1147us @ 8Mhz
+            #define LOOP_CYCLES_CHAR    9                    //how many cycles per loop, optimizations on
+            #define timeout_char_us(x)    (unsigned char)((x/LOOP_CYCLES_CHAR)*(PIC_CLK/4.0))
+            unsigned char timeout;
+            timeout=timeout_char_us(1147);                        //max timeout allowed @ 8Mhz, 573us @ 16Mhz
+            while((timeout-- >= 1) && (<extra condition>));    //wait
+
+To use:        //for max 491512us, half sec timeout @ 8Mhz
+            #define LOOP_CYCLES_INT        16                    //how many cycles per loop, optimizations on
+            #define timeout_int_us(x)    (unsigned int)((x+/LOOP_CYCLES_INT)*(PIC_CLK/4.0))
+            unsigned int timeout;
+            timeout=timeout_int_us(491512);                        //max timeout allowed @ 8Mhz
+            while((timeout-- >= 1) && (<extra condition>));    //wait
+*/
+
+
+//function prototypes
+void DelayBigUs(unsigned int cnt);
+void DelayMs(unsigned char cnt);
+void DelayMs_interrupt(unsigned char cnt);
+void DelayBigMs(unsigned int cnt);
+void DelayS(unsigned char cnt);
+
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fat.c	Mon Aug 22 05:48:51 2011 +0000
@@ -0,0 +1,569 @@
+/*-----------------------------------------------------------------------------------*/
+/* This is a simple FAT16 handler. It works on a sector basis to allow fastest acces */
+/* on disk images.                                                                   */
+/*                                                                                     */
+/* Attention: when using Roadkill sector editor, chose the physical disk, and not the*/
+/* drive number, otherwise the calculated sectors will not allways be the identical  */
+/*-----------------------------------------------------------------------------------*/
+/*    History:
+    2008-02-08    fixed the problem regarding the backwards searching within subdirectories
+                As this only is a problem with the use of the buttons... it was discovered at the last moment and now it is fixed. Subdirectories are now FULLY functional <hurray>
+    2008-02-01    improved filesearch routine for subdirectory support, it appears to work
+    2008-01-18    worked on opendirectory
+    2008-01-14    corrected a small bug, because of the ASCII to PETSCII conversiuon, the calculation of the 8.3 checksum was incorrect
+                by using the RAW-data (unconverted filename) the checksum can be calculated as it should and it all works while keeping readable characters on your retro computer
+    2008-01-09    improved routine opensubdirectory(), suddenly it all works (hurray)
+    2008-01-07    added routine opensubdirectory(), this makes suport of subdirectories a fact
+    2007-12-20    added ASCII to PETSCII routines
+    2007-12-19    playing with longfilenames
+    2007-04-07    Mattias Olsson reported the following bugfix:
+                By changing every occurrence of: sb+=clustersize*(file->cluster-2);
+                to :                             sb+=(unsigned long)clustersize*(file->cluster-2); 
+                I can now load every file on the card. This bug caused problem when a lot of files were stored on the card (i.e. more then 340).
+                Thanks Mattias, this saved me a lot of work, these bugs are the worst to fix.
+    2006-12-15    fixed a small bug important bug in the FATSTART calculation (566 and 567 instead of 556 and 557)
+                depending on your card it should not cause to much trouble...
+    2006-09-03    renamed "databuffer" to "block_buffer" since this is a more appropriate name
+    2006-08-21    added more debugging info in order to find the problem regarding the problems with some card not being supported...
+    2006-04-11    improved 'FindDrive' routine to support cards without a partition table
+    2006-02-03    added filesize to file structure (userfull for simple and quick file type validation of fixedsize files (i.e. D64-files))
+    2006-02-02    improvements in code layout... i.o.w. making it more readable
+    2006-02-02    also the sector number is relevant... fixed it
+    2006-02-01    added cache-ing regarding sector locations
+    2006-01-31    worked out how to write the byte addressable read routine
+    2006-01-29    added first steps for byte addressable read routine (read X bytes from startaddress Y)
+    2005-12-23    added current file search option
+    2005-12-11    first version, ported from FAT1618.C
+*/
+
+/* TO DO:
+   ------
+    - FileSectorScan(struct file2TYPE *file) routine iets aanpassen zodat we niet falen op de theoretisch laatste 'filenextsector'
+*/
+
+/*----------------------------------------------------------------------------------*/
+                
+/*--------------------------------------------------------*/
+/*                        includes                        */
+/*--------------------------------------------------------*/
+#include <stdio.h>
+#include <main.h>
+#include <ata.h>
+#include <fat.h> 
+
+/*--------------------------------------------------------*/
+/*                        constants                       */   
+/*--------------------------------------------------------*/
+#define        FALSE                            0            /*FALSE*/
+#define        TRUE                            1            /*TRUE*/
+
+/*Since the size of a D64 file is fixed the number of sectors required for a D64 file is also fixed*/
+/*In order to keep compatibillity with most of the .D64 formats we must be able to handle the biggest,*/
+/*so thats 40tracks including error bytes*/
+#define        D64FileConsistsOfSectors        386            /*(768(40tracks disk) * 256(bytes per block)) / 2 = 384 x 512(bytes per block), including the 768 error bytes (1.5x512) that would make a total of 386 blocks*/
+
+/*--------------------------------------------------------*/
+/*                         globals                        */
+/*--------------------------------------------------------*/
+static unsigned long fatstart;                    /*start LBA of first FAT table*/
+static unsigned char fatno;                     /*number of FAT tables*/
+static unsigned long datastart;                   /*start LBA of data field*/
+static unsigned long rootstart;                   /*start LBA of rootdirectory table*/
+static unsigned short direntrys;                 /*number of entry's in directory table*/
+static unsigned short direntrys_root;              /*number of entry's in directory table*/
+static unsigned char clustersize;                 /*size of a cluster in blocks*/
+static unsigned short subdircluster_start;        /*starting cluster of subdirectory*/
+static unsigned short subdirsec_start;            /*starting cluster of subdirectory*/
+#define bit bool
+static bit root;
+
+
+unsigned short clusterlocationcache[D64FileConsistsOfSectors];            /*cache for the sector locations within the D64 file as stored in the Fat16*/
+
+/*--------------------------------------------------------*/
+/*                     local functions                    */
+/*--------------------------------------------------------*/
+
+unsigned char ASCII_to_PETSCII(unsigned char ASCII);
+
+/*****************************************************************************************************************/
+/*****************************************************************************************************************/
+
+/*FindDrive checks if a card is present. if a card is present it will check for
+a valid FAT16 primary partition*/
+unsigned char FindDrive(void)
+{
+    unsigned char error_code;
+    unsigned long fatsize;                /*size of fat*/
+    unsigned long dirsize;                /*size of directory region in sectors*/
+        
+    error_code = AtaReadSector(0,block_buffer);    /*read partition sector*/
+    if (error_code != TRUE)
+    {
+        return(error_code);
+    }
+    
+    /*Check for partition table, when this can not be found then set "fatstart=0" (to support cards (SUPERFLOPPY's) that have no partition table) and to support extended partitions*/
+    if(block_buffer[450]!=0x04 && block_buffer[450]!=0x05 && block_buffer[450]!=0x06)/*check partition type*/
+        fatstart=0;
+    else if(block_buffer[510]!=0x55 || block_buffer[511]!=0xaa)    /*check signature*/        
+        fatstart=0;
+    else
+    {
+        fatstart=(unsigned long)block_buffer[454];                /*get start of first partition*/
+        fatstart+=(unsigned long)block_buffer[455]*256;
+        fatstart+=(unsigned long)block_buffer[456]*65536;
+        fatstart+=(unsigned long)block_buffer[457]*16777216;
+    }
+            
+    if(!AtaReadSector(fatstart,block_buffer))                    /*read boot sector*/
+        return(ERROR_FAT_READBOOTSECTOR);    
+    
+    if(block_buffer[0]!=0xe9 && block_buffer[0]!=0xeb)            /*check for near-jump or short-jump opcode*/
+        return(ERROR_FAT_JUMPOPCODE);
+    
+    if(block_buffer[11]!=0x00 || block_buffer[12]!=0x02)        /*check if blocksize is really 512 bytes*/
+        return(ERROR_FAT_BLOCKSIZE);
+    
+    if(block_buffer[21]!=0xf8)                                    /*check medium descriptorbyte, must be 0xf8 for hard drive*/
+        return(ERROR_FAT_MEDIUM);
+    
+    direntrys=block_buffer[17]+(block_buffer[18]*256);            /*calculate drive's parameters from bootsector, first up is size of directory*/
+    direntrys_root = direntrys;
+    dirsize=((direntrys*32)+511)/512;                  
+    
+    fatstart=fatstart+block_buffer[14]+(block_buffer[15]*256);    /*calculate start of FAT,size of FAT and number of FAT's*/
+    fatsize=block_buffer[22]+(block_buffer[23]*256);
+    fatno=block_buffer[16];
+    
+     rootstart=fatstart+(fatno*fatsize);                            /*calculate start of root-directory*/
+     clustersize=block_buffer[13];                                /*get clustersize*/
+    datastart=rootstart+dirsize;                                  /*calculate start of data*/   
+    root=TRUE;                                                     /*raise flag to indicate we are in the root directory*/
+      return(TRUE);
+}
+
+/*this routine needs to be called when a subdirectory is entered*/
+/*this routine re-calculates the current directroy pointers and registers to those of the (sub)directory to be opened*/ 
+/*this routine returns TRUE when the subdirectory is a subdirectory and FALSE when it is root*/
+unsigned char OpenSubDirectory(struct file2TYPE *file)
+{
+    /*calculate the location of the first byte of the new (sub)directory*/
+    if(file->cluster == 0)                                    /*check if the user requests the root directory*/
+    {                                                        /*---------------------------------------------*/
+        root=TRUE;                                              /*raise flag to indicate we are in the root directory*/
+        direntrys = direntrys_root;
+        return(FALSE);                                        /*we are now back in root*/
+    }
+    else
+    {
+        root=FALSE;                                         /*lower flag to indicate we are NOT in the root directory*/
+        direntrys = 1000;                                     /*a fixed value that is practically impossible to use on a CBM computer*/
+        subdircluster_start = file->cluster;                /*starting cluster of subdirectory*/    
+        subdirsec_start = file->sec;                        /*starting sector offset within cluster*/
+        return(TRUE);                                        /*we are now in a subdirectory*/
+    }    
+}
+
+/*scan directory, yout must pass a file handle to this function*/
+/*search modes: 0=first,1=next(8.3 AND LFN),2=previous(8.3 only),3=current*/
+unsigned char FileSearch(struct file2TYPE *file, unsigned char mode)
+{
+    static unsigned short subdircluster_current;    /*current cluster of subdirectory*/
+    static unsigned short subdirsec_current;        /*current sector offset within cluster*/
+    static unsigned char sectorcounter;                /*a relative counter, to keep track of how many sectors we've read regarding this subdirectory*/
+    /*sectorcounter: this is an unsigned char, meaning that this limits a subdir to have "only" 255*16 8.3 file entries. Which is a lot for a retro computer*/
+
+    unsigned long sf,sb;
+    unsigned short i;
+    unsigned char j;
+
+    unsigned short LFN_offset;
+    unsigned char LFN_seq_nmbr;
+    unsigned char LFN_string[27];    /*the length of the LFN name we use is max 26 characters (2 LFN entries)*/
+    unsigned char LFN_checksum[2];    /*since we use only two LFN entries, we only need to store 2 checksums*/
+    unsigned char REF_checksum;        /*the checksum which is our reference*/
+
+    LFN_checksum[0] = 0;            /*clear the checksum value of the 1st LFN sequence*/
+    LFN_checksum[1] = 0;            /*clear the checksum value of the 2nd LFN sequence*/
+    
+    sb=0;                            /*buffer is empty*/
+    if(mode==0)            /*search for first entry*/
+    {                    /*----------------------*/
+        file->entry=0;
+        if (root == FALSE)
+        {
+            file->cluster = subdircluster_start;            /*reset the cluster pointer back to the beginning of the directory, otherwise we fail with the filenextsector routine*/
+            file->sec = subdirsec_start;                    /*starting sector offset within cluster*/
+            subdircluster_current = file->cluster;
+            subdirsec_current = file->sec;
+            sectorcounter = 0;
+        }
+    }
+    else if(mode==1)    /*search for next entry*/
+    {                    /*---------------------*/
+        file->entry++;
+    }
+    else if(mode==2)    /*search for previous entry*/
+    {                    /*-------------------------*/
+        file->entry--;
+    }
+
+    while(file->entry<direntrys)
+    {    
+        if (root == TRUE)            /*the root directory is one continuos chunk of entries*/
+        {                            /*----------------------------------------------------*/
+            sf=rootstart;            /*calculate sector and offset*/
+            sf+=(file->entry)/16;    /*16 entries fit into one sector, so when entry = 16 (or 32,48, etc), we need to load a new sector (indicated by SF incremented by one)*/
+    
+            if(sb!=sf)                /*when buffer is empty or needs to be changed*/
+            {
+                sb=sf;
+                if(!AtaReadSector(sb,block_buffer))
+                    return(FALSE);    
+            }
+        }
+        else                        /*subdirectory entries can be scattered all over the disk, so in order to determine where the next cluster is we need to lookup this info in the FAT*/
+        {                            /*--------------------------------------------------------------------------------------------------------------------------------------------------*/
+            if((mode==1) && (file->entry > 0) && (file->entry%16 == 0))    /*load sector if not in buffer*/
+            {
+                file->cluster = subdircluster_current;                    /*retrieve the latest cluster value*/
+                file->sec = subdirsec_current;                            /*retrieve the latest sector value*/    
+                if (FileNextSector(file) == FALSE)                        /*attention: screws up block_buffer!!*/
+                    return(FALSE);
+                sectorcounter++;                                        /*another sector loaded, increment counter*/
+                subdircluster_current = file->cluster;                    /*save the new value for later*/
+                subdirsec_current = file->sec;                            /*save the new value for later*/
+    
+                if ((file->cluster & 0xFFF8) ==  0xFFF8)                /*check if this is the last cluster*/
+                {
+                    file->len=0;    
+                    return(FALSE);
+                }
+            }
+
+
+             if((mode==2) &&  ((file->entry + 1) > 0) && ((file->entry+1)%16 == 0))    /*load sector if not in buffer*/
+            {
+                /*because directory are not designed to be read in a reverse direction, we need to rescan the previous clusterchain in order to find the previous cluster*/
+                /*this is the only way because FAT only stores the next cluster, which is useless if you want the previous. So we start at the first cluster and skip all cluster untill we reach the desired (previous from the current)*/
+                file->cluster = subdircluster_start;                    /*reset the cluster pointer back to the beginning of the directory, otherwise we fail with the filenextsector routine*/
+                file->sec = subdirsec_start;                            /*starting sector offset within cluster*/
+                if (sectorcounter > 0)
+                {
+                    sectorcounter--;                                    /*previous sector found, decrement counter*/
+                    for(j=0;j<sectorcounter;j++)
+                    {
+                        if (FileNextSector(file) == FALSE)                /*attention: screws up block_buffer!!*/
+                            return(FALSE);
+                    }        
+                }
+                subdircluster_current = file->cluster;                    /*save the new value for later*/
+                subdirsec_current = file->sec;                            /*save the new value for later*/
+            }        
+
+            sf=datastart;                                                /*start of data in partition*/
+            sf+=(unsigned long)clustersize*(subdircluster_current-2);    /*cluster offset*/
+            sf+=(subdirsec_current%clustersize);                         /*sector offset in cluster*/
+            if(sb!=sf)                                                    /*when buffer is empty or needs to be changed*/
+            {
+                sb=sf;
+                if(!AtaReadSector(sb,block_buffer))
+                    return(FALSE);    
+            }
+        }
+
+        i=(file->entry%16)*32;            /*i is the pointer that points to the address of the entry within the loaded sector*/
+        if(block_buffer[i+0x0b]==0x0f)    /*check if this entry is an LFN entry*/
+        {
+            //if(block_buffer[i]<=0x55)    /*check the LFN sequence number the highest possible value would be 0x55 (20th entry which is the last entry (0x15 OR-ed with 0x40)*/
+            if(block_buffer[i]<=0x42)    /*check the LFN sequence number. Although the highest possible value would be 0x55, this application only uses 2 LFN entries (26 chars), since we can only display 16 characters within a CBM directory*/
+            {
+                LFN_seq_nmbr = block_buffer[i] & 0x3f;    /*remove the possible 0x40 in order to keep the bare LFN sequence number*/
+                LFN_offset = (LFN_seq_nmbr * 13) - 13;
+
+                /*save the LFN characters to the correct location of our string*/
+                LFN_string[LFN_offset + 0] = block_buffer[i+0x01];    /*5 UTF characters of which we only use the first byte*/
+                LFN_string[LFN_offset + 1] = block_buffer[i+0x03];
+                LFN_string[LFN_offset + 2] = block_buffer[i+0x05];
+                LFN_string[LFN_offset + 3] = block_buffer[i+0x07];
+                LFN_string[LFN_offset + 4] = block_buffer[i+0x09];
+
+                LFN_checksum[LFN_seq_nmbr-1] = block_buffer[i+0x0d];/*save the checksum*/
+
+                LFN_string[LFN_offset + 5] = block_buffer[i+0x0e];    /*6 UTF characters of which we only use the first byte*/
+                LFN_string[LFN_offset + 6] = block_buffer[i+0x10];
+                LFN_string[LFN_offset + 7] = block_buffer[i+0x12];
+                LFN_string[LFN_offset + 8] = block_buffer[i+0x14];
+                LFN_string[LFN_offset + 9] = block_buffer[i+0x16];
+                LFN_string[LFN_offset + 10] = block_buffer[i+0x18];
+
+                LFN_string[LFN_offset + 11] = block_buffer[i+0x1c];    /*2 UTF characters of which we only use the first byte*/
+                LFN_string[LFN_offset + 12] = block_buffer[i+0x1e];
+    
+            /*the following code is not required as we only use two LFN entries which we compare with a checksum later*/
+            /*the code below is left for reference for LFN filenames which must be longer then 26chars*/
+            //    if(block_buffer[i]&0x40 == 0x40)                    /*check if this entry was the last LFN entry belonging to this file*/
+            //    {                                                    /*we do this by checking if the 6st bit was set*/
+            //        LFN_string[LFN_offset + 13] = 0;                /*terminate string HERE*/
+            //    }
+            }
+        }
+
+        if(block_buffer[i]!=0x00 && block_buffer[i]!=0xe5)                /*check if valid file entry: 0x00 = entry is available*/
+        {    /*                                                                                       0xE5 = entry has been erased*/
+            if((block_buffer[i+0x0b]&0x0a)==0x00)                        /*check atributes: do not show hidden files, do not show volume labels, DO SHOW subdirectories*/
+            {
+                for(j=0;j<11;j++)                                       /*copy name (8.3)*/
+                    file->name[j] = ASCII_to_PETSCII(block_buffer[i+j]); /*copy each character and substitute the following ASCII-chars to PETSCII alternatives. Because we convert it here, we do not have to convert it back in the file search routines which effectively results in simpler and (even better) shorter code*/
+                file->name[j]=0x00;                                        /*terminate the string*/
+            
+                file->len=(unsigned long)block_buffer[j+28];            /*get length of file in sectors, maximum is 16Mbytes*/
+                file->len+=(unsigned short)block_buffer[i+29]*256;
+                file->len+=511;
+                file->len/=512;
+                file->len+=(unsigned long)block_buffer[i+30]*128;
+                        
+                file->cluster=(unsigned long)block_buffer[i+26]+((unsigned long)block_buffer[i+27]*256);    /*get first cluster of file*/            
+                file->size = (unsigned long)block_buffer[i+28]+((unsigned long)block_buffer[i+29]*256)+((unsigned long)block_buffer[i+30]*65536)+((unsigned long)block_buffer[i+31]*16777216);
+                file->sec=0;                                                                    /*reset sector index*/                        
+
+                REF_checksum = 0;                                    /*calculate the checksum of the 8.3 filename*/ 
+                for (j=0;j<11;j++)                                    /*this checksum is our reference to which we compare the LFN checksum(s) with*/
+                    REF_checksum = (((REF_checksum & 1) << 7) | ((REF_checksum & 0xfe) >> 1)) + block_buffer[i+j]; 
+
+                if(LFN_checksum[0] == REF_checksum)                    /*using the checksum we determine wether we use the gathered LFN information*/
+                {
+                    for(j=0;j<13;j++)                                   /*copy the first 13 characters of the LFN string (maintain case)*/
+                        file->name_lfn[j] = ASCII_to_PETSCII(LFN_string[j]); /*substitute the following ASCII-chars to PETSCII alternatives. Because we convert it here, we do not have to convert it back in the file search routines which effectively results in simpler and (even better) shorter code*/
+
+                    if(LFN_checksum[1] == REF_checksum)
+                    {
+                        for(j=12;j<26;j++)                           /*copy the last few characters of the LFN string so that we have a total of max. 16 characters (maintain case)*/
+                            file->name_lfn[j] = ASCII_to_PETSCII(LFN_string[j]); /*substitute the following ASCII-chars to PETSCII alternatives. Because we convert it here, we do not have to convert it back in the file search routines which effectively results in simpler and (even better) shorter code*/
+                        file->name_lfn[26]=0x00;                    /*terminate string*/
+                    }
+                    else
+                        file->name_lfn[13]=0x00;                    /*terminate string*/
+                }
+                else
+                {
+                    file->name_lfn[0]=0;            /*clear the LFN string by terminating at the first char*/
+                }
+
+                return(TRUE);
+            }
+        }
+        if(mode==2)
+            file->entry--;
+        else
+            file->entry++;
+    }
+    file->len=0;        
+    return(FALSE);
+}
+
+
+/*this routine will scan for the startaddress of all possible sectors that hold a D64 file*/
+unsigned char FileSectorScan(struct file2TYPE *file)
+{
+    unsigned int lp;
+
+    for(lp=0; lp<(D64FileConsistsOfSectors-1); lp++)        
+    {
+        clusterlocationcache[lp] = file->cluster;
+        if (FileNextSector(file) == FALSE)                /*attention: screws up block_buffer!!*/
+            return(FALSE);
+    }
+    clusterlocationcache[D64FileConsistsOfSectors-1] = file->cluster;
+
+    return(TRUE);
+}
+
+
+/*point to next sector in file*/
+unsigned char FileNextSector(struct file2TYPE *file)
+{
+    unsigned long sb;
+    unsigned short i;
+    
+    file->sec++;                        /*increment sector index*/
+    if((file->sec%clustersize)==0)        /*if we are now in another cluster, look up cluster*/
+    {
+        sb=fatstart;                    /*calculate sector that contains FAT-link*/
+        sb+=(file->cluster/256);
+        i=(file->cluster%256);            /*calculate offset*/
+        i*=2;
+        
+        if(!AtaReadSector(sb,block_buffer))    /*read sector of FAT*/
+            return(FALSE);
+            
+        file->cluster=((unsigned short)block_buffer[i+1]*256)+(unsigned short)block_buffer[i];    /*get FAT-link*/
+    }
+    return(TRUE);
+}
+
+/*read current sector into buffer*/
+unsigned char FileReadSector(struct file2TYPE *file)
+{
+    unsigned long sb;
+    
+    sb=datastart;                                        /*start of data in partition*/
+    sb+=(unsigned long)clustersize*(file->cluster-2);    /*cluster offset*/
+    sb+=(file->sec%clustersize);                         /*sector offset in cluster*/
+                            
+    if(!AtaReadSector(sb,block_buffer))                    /*read the data from the sector*/
+        return(FALSE);
+    else
+        return(TRUE);
+}
+
+/*read specified sector into buffer*/
+unsigned char FileReadSector_X(struct file2TYPE *file, unsigned long block)
+{
+    unsigned long sb;
+    
+    file->cluster = clusterlocationcache[block];        /*retrieve the sector address from the cache*/
+    file->sec = block;                                    /*we need to indicate the exact sector number within this cluster*/
+
+    sb=datastart;                                        /*start of data in partition*/
+    sb+=(unsigned long)clustersize*(file->cluster-2);    /*cluster offset*/
+    sb+=(file->sec%clustersize);                         /*sector offset in cluster*/
+//    sb+=pt;                                                /*add the pointer offset to the absolute address of the data position as stored on the card*/
+
+    if(!AtaReadSector(sb,block_buffer))                    /*read the data from the sector*/
+        return(FALSE);
+    else
+        return(TRUE);
+}
+
+/*Read xxx bytes from a sector into a specified buffer*/
+/*When only one or more bytes are required, then this routine comes in handy...*/
+unsigned char FileRead_X_Bytes(struct file2TYPE *file, unsigned long startaddress, unsigned int NmbrOfBytes)
+{
+    unsigned long lp, pt, bytesfromcurrentsector, bytesfromnextsector;
+    unsigned long sb;
+
+    lp = startaddress/512L;                /*determine how many (512byte) sectors we must skip before we find our desired byte (512=size of a MMC and SD-card sector)*/
+    pt = startaddress%512L;                /*the byte we are looking for is pointed to by "cardbuffer_pnt"*/
+    
+    /*check if the bytes we want to read beyond the sector border*/
+    if ((pt + NmbrOfBytes) < 512L)
+    {
+        bytesfromcurrentsector = NmbrOfBytes;    /*the number of bytes that can be read from the now selected sector*/
+        bytesfromnextsector = 0;                /*the number of bytes that can cannot be read from the now selected sector and must be read from the next sector*/
+    }
+    else
+    {
+        bytesfromcurrentsector = 512L - pt;                            
+        bytesfromnextsector = NmbrOfBytes - bytesfromcurrentsector;    
+    }
+
+    file->cluster = clusterlocationcache[lp];        /*retrieve the sector address from the cache*/
+    file->sec = lp;                        /*we need to indicate the exact sector number within this cluster*/
+
+    sb=datastart;                        /*start of data in partition*/
+    sb+=(unsigned long)clustersize*(file->cluster-2);    /*cluster offset*/
+    sb+=(file->sec%clustersize);         /*sector offset in cluster*/
+//    sb+=pt;                                /*add the pointer offset to the absolute address of the data position as stored on the card*/
+    if(!AtaRead_X_Bytes(sb, pt, block_buffer, bytesfromcurrentsector))        /*read data (a part of the current sector) from drive*/
+        return(FALSE);
+
+    if (bytesfromnextsector !=0)
+    {
+        file->cluster = clusterlocationcache[lp+1];    /*retrieve the sector address from the cache*/
+        file->sec = lp+1;                    /*we need to indicate the exact sector number within this cluster*/
+
+        sb=datastart;                        /*start of data in partition*/
+        sb+=(unsigned long)clustersize*(file->cluster-2);    /*cluster offset*/
+        sb+=(file->sec%clustersize);         /*sector offset in cluster*/
+        if(!AtaRead_X_Bytes(sb, 0, &block_buffer[bytesfromcurrentsector+1], bytesfromnextsector))        /*read data (a part of the current sector) from drive*/
+            return(FALSE);
+    }
+    return(TRUE);
+}
+
+/*Write the specified block to the card*/
+unsigned char FileWriteSector_X(struct file2TYPE *file, unsigned long block)
+{
+    unsigned long sb;
+    
+    file->cluster = clusterlocationcache[block];    /*retrieve the sector address from the cache*/
+    file->sec = block;                                    /*we need to indicate the exact sector number within this cluster*/
+
+    sb=datastart;                        /*start of data in partition*/
+    sb+=(unsigned long)clustersize*(file->cluster-2);    /*cluster offset*/
+    sb+=(file->sec%clustersize);         /*sector offset in cluster*/
+//    sb+=pt;                                /*add the pointer offset to the absolute address of the data position as stored on the card*/
+    if(!AtaWriteSector(sb,block_buffer))    /*write data to medium*/
+        return(FALSE);
+
+    return(TRUE);
+}
+
+
+/***************************************************************************************************************************************/
+
+/*convert ASCII to PETSCII: substitute the following ASCII-chars to PETSCII alternatives*/                
+unsigned char ASCII_to_PETSCII(unsigned char ASCII)
+{
+    unsigned char PETSCII;
+
+    if ((ASCII >= 'a') && (ASCII <= 'z'))    /*check if the ASCII character is lowercase*/
+    {
+        ASCII = ASCII - 0x20;     /*convert lowercase to UPPERCASE*/
+    }
+
+    switch (ASCII)
+            {    
+                case 0x5e:            /*^-sign (caret)*/
+                {
+                    PETSCII = 0xb1;    /*PETSCII small 4 pixel upsidedown T located at the top*/
+                    break;
+                }
+
+                case 0x5F:            /*_-sign (underscore)*/
+                {
+                    PETSCII = 0xa4;    /*PETSCII underscore*/
+                    break;
+                }
+
+                case 0x60:            /*'-sign (single quote)*/
+                {
+                    PETSCII = 0xbe;    /*PETSCII 4pixel square located top left*/
+                    break;
+                }
+
+                case 0x7b:            /*{-sign (bracket left)*/
+                {
+                    PETSCII = 0x5b;    /*PETSCII squared bracket left*/
+                    break;
+                }
+
+                case 0x7d:            /*}-sign (bracket right)*/
+                {
+                    PETSCII = 0x5d;    /*PETSCII squared bracket right*/
+                    break;
+                }
+
+                case 0x7e:            /*~-sign (tilde as we say in Dutch)*/
+                {
+                    PETSCII = 0xA8;    /*PETSCII tilde*/
+                    break;
+                }
+
+                default:    /*in all other undefined situations leave the character "as it was"*/
+                {
+                    PETSCII = ASCII;
+                    break;    
+                }
+            }
+    return(PETSCII);
+}
+
+/***************************************************************************************************************************************/
+/***************************************************************************************************************************************/
+/***************************************************************************************************************************************/
+/***************************************************************************************************************************************/
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fat.h	Mon Aug 22 05:48:51 2011 +0000
@@ -0,0 +1,31 @@
+#ifndef _FAT_H_INCLUDED
+#define _FAT_H_INCLUDED
+
+struct file2TYPE
+{
+    unsigned char    name[12];           /*name of file*/
+    unsigned char    name_lfn[27];         /*name of file according the long-file-name information*/
+    unsigned short    entry;                /*file-entry index in directory table*/
+    unsigned short    sec;                  /*sector index in file*/
+    unsigned short    len;                /*total number of sectors in file, 0 if not a file*/
+    unsigned long    size;                /*filesize in bytes*/
+    unsigned short    cluster;            /*current cluster*/    
+};
+
+/*functions*/
+unsigned char FindDrive(void);
+unsigned char FileSearch(struct file2TYPE *file, unsigned char mode);    /*attention: screws up secbuf!!*/
+unsigned char OpenSubDirectory(struct file2TYPE *file);
+unsigned char FileSectorScan(struct file2TYPE *file);
+unsigned char FileNextSector(struct file2TYPE *file);                    /*attention: screws up databuffer!!*/
+unsigned char FileReadSector(struct file2TYPE *file);                    /*attention: secbuf is valid after this command*/
+unsigned char FileReadSector_X(struct file2TYPE *file, unsigned long block);
+unsigned char FileRead_X_Bytes(struct file2TYPE *file, unsigned long startaddress, unsigned int NmbrOfBytes);
+unsigned char FileWriteSector_X(struct file2TYPE *file, unsigned long block);
+
+#define        ERROR_FAT_READBOOTSECTOR        30
+#define        ERROR_FAT_JUMPOPCODE            31
+#define        ERROR_FAT_BLOCKSIZE                32
+#define        ERROR_FAT_MEDIUM                33
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hardware.c	Mon Aug 22 05:48:51 2011 +0000
@@ -0,0 +1,74 @@
+/*----------------------------------------------------------------------------------*/
+/*            1541-III, Hardware control routines, Written by Jan Derogee           */
+/*----------------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------------*/
+
+/*  History:                                                                        
+    --------    
+    2007-03-08    status of LED output was set to 1 (LED-ON) during config, must be 0 (LED-OFF)
+    2006-06-22    changed baudrate to 115K2, this is more practical/compatible with the bootloader (currently)
+    2006-06-21    added complete device configuration word, witout it the source is not complete
+                in previous versions the user had to set the configuration word within MPLAB
+                but to make this source independent, the configuration word must be included here!!
+                and NOT in the development environment. Doing it within the source also documents it.
+    2006-04-12    enabled interrupt on RB0 (for ATN handling under interrupt)
+    2006-03-28    change in IO-pin definiions required for new PCB design
+    2006-02-04    added timer-0 (for the led blinking routines)
+    2006-02-02    improvements in code layout... i.o.w. making it more readable
+
+*/
+
+/*  TO DO:                                                                          
+    ------      
+*/
+
+/*----------------------------------------------------------------------------------*/
+
+
+/*--------------------------------------------------------*/
+/*                        includes                        */
+/*--------------------------------------------------------*/
+#include <mbed.h>
+//#include <IEC_bus.h>
+
+#include <hardware.h> 
+
+/*--------------------------------------------------------*/
+/*                         globals                        */
+/*--------------------------------------------------------*/
+bool    std_out;        /*this holds the destination of the putch- and printf-routines*/
+/*--------------------------------------------------------*/
+
+/*****************************************************************************************************************/
+/*****************************************************************************************************************/
+
+void HardwareInit(void)        /*initialize processor here*/
+{
+ 
+ 
+    
+//    INTEDG0    = 0;    /*set interrupt trigger to falling edge*/
+//    INT0IE    = 0;    /*disable interrupts on pin RB0 (INT0), this line is connected to the ATN line*/
+
+//    IPEN=1;            /*enable priority for interrrupts*/
+//    PEIE=1;
+//    GIE=1;
+}
+
+extern void enable_ATN_interrupt(void);
+
+#define RS232 1
+#define LCD 0
+
+/*redirect standard output to serial or LCD*/
+void putch(unsigned char ch) 
+{
+   
+            putchar(ch);      
+ }
+
+
+    
+/*
+The author of sourcecode without comments is the only one to fully understand the written code... for the first 3 months.
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hardware.h	Mon Aug 22 05:48:51 2011 +0000
@@ -0,0 +1,33 @@
+#ifndef _HARDWARE_H_INCLUDED
+#define _HARDWARE_H_INCLUDED
+
+                                                                                                                                                                                                                                                        
+/* IO defines */
+/*------------*/
+
+extern int IEC_CLOCK();
+extern int IEC_DATA();
+extern int IEC_ATN();
+extern void IEC_DATA_REL();
+extern void IEC_CLOCK_REL();
+extern void IEC_DATA_PULL();
+extern void IEC_CLOCK_PULL();
+
+/*--------------------------------------------------------*/
+/*                         macro's                        */
+/*--------------------------------------------------------*/
+#define            RS232            1    /*standard out = RS=232*/
+#define            LCD              0    /*standard out = LCD*/
+
+#define bit bool
+extern bit        std_out;            /*this holds the destination of the putch- and printf-routines*/
+
+
+
+#define        OutputToRS232()        std_out=RS232
+#define        OutputToLCD()        std_out=LCD
+
+
+void HardwareInit(void);
+void putch(unsigned char ch);
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.c	Mon Aug 22 05:48:51 2011 +0000
@@ -0,0 +1,4114 @@
+/*==================================================================================*/
+/*==   This software is designed to be compiled by the Hi-Tech PIC Ccompiler      ==*/
+/*==                                                                              ==*/
+/*==   Attention, make sure to compile with the following options selected:       ==*/
+/*==           printf: integer + long + float                                        ==*/
+/*==================================================================================*/
+/*  1541-III (simply said: a 1541 clone that uses MMC/SD-cards)                     */
+/*                                                                                  */
+/*                                  This is MAIN                                    */
+/*                                  ------------                                    */
+/*                                                                                  */
+/* This program is designed to control the 1541-III project:                        */
+/* The 1541-III project is a device to be connected to the IEC-bus of a C64         */
+/* The device will act as if it was a 1541 diskdrive. The diskimages are to be      */
+/* stored on a MMC or SD-card in the D64 file format (the most common emulator file */
+/* for C64 disk images. By selecting a specific D64 file on the card you select the */
+/* diskimage to be seen by the connected C64. By mimmicing a 1541 drive the C64 does*/
+/* not require any extra software while keeping the flexability of a modern medium. */
+/* This way the huge amount of software on the WEB becomes available on your stock  */
+/* C64, like the good old days, checking out your new 'disks' full with hours of fun*/
+/*                                                                                  */
+/* Note:                                                                            */
+/* a sector on a 5,25" disk has the size of 256 bytes, this is also called a block  */
+/*                                                                                  */
+/*      ATTENTION: all settings are calculated for a crystal freq. of 20MHz         */
+/*                                                                                  */
+/*----------------------------------------------------------------------------------*/
+
+#define            RELEASE_VERSION            8    /*last 2 digits of Year    */
+#define            RELEASE_VERSION_SUB        2    /*Month                    */
+#define            RELEASE_VERSION_SUB_SUB    27    /*Day                    */
+
+/*  History:                                                                    
+    --------      
+
+    IMPORTANT to implement ASAP, IEC abort: the computer sends an ATN during data transfer from device to computer, the device sees that this is a special situation and aborts, freeing up the bus and the computer will get it's prompt back (test this by loading a program and pressing run/stop during loading)
+    (this information was supplied by: Dirk (a.k.a. SKERN, from www.dienstagstreff.de)
+
+    debug datahandler!!!
+    2011-08-22  First version of this software ported to mbed by Gert van der Knokke
+    2008-02-27    release date of this wonderfull version
+    2008-02-20    removed the T64 detection in the filefilter routine. Simply because the T64 is not supported yet and showing the T64 files in the card directory would give the wrong impression or simply said it would be confusing.
+    2008-02-17    fixed the spaces at the end of a filename-bug (in routine D64Directory()). When a filename has normal (0x20) spaces at the end these are filtered out, so you do not see them in the loaded directory. But since the fileseek routines encounter them they never will report a match (because the last two chars (spaces) are missing)
+                The routine ImageDirectory is renamed to D64Directory simply because the D64 directory routine cannot easily be transformed into something universal
+    2008-02-15    added a default value to error_code declaration
+                made the separation line in the card-directory a bit nicer and added an extra check that removed the undesired first seperator line
+    2008-02-14    changed the serial debugging output to some nice ASCII/art looking debugging output (filling some spare minutes)
+                did some T64-file preparations...
+    2008-02-12    The save bug as reported 21-08-2007 by: Andreas Ekmark    - "File not found error" if the save was successful.    - "File found ok" if the save failed
+                As suggested this is indeed the status from the "does file exist" check that must occur prior tosaving that is still reported after the save... 
+                The probem lies in the not correctly updating of the display and the incorrect updating of the register error_code in the routine set errorcode
+    2008-02-11    fixed a problem with the 1541-III powered directly by the VIC20's cassetteport. The 1541-III will hang with the drive LED=green and the LCD in the splash-screen mode. This problem does not occur when the 1541-III is in bootloader-mode. It appears that the VIC20's IEC bus is not stable directly after powerup (causing the 1541-III to trigger falsely and wainting endlessly for signals that never come. Waiting for 2 seconds (as a normal drive does) and then enabling the ATN interrupt solves this problem.
+    2008-02-10    removed write protect check as it does not have any value and can be very anoying
+                so now you can use a card wether it is or isn't write protected with the "switch" on the side (SD-card card only)
+    2008-02-08    fixed the problem in FAT.c (filesearch) regarding the backwards searching within subdirectories.
+                As this only is a problem with the use of the buttons... it was discovered at the last moment and now it is fixed. Subdirectories are now FULLY functional <hurray>
+    2008-02-05    tested the VIC20 mode on a real vic20, and as expected, there where still too much chars on one line, fixed
+    2008-02-04    fixed a smull bug in seekfileoncard() routine. it failed in finding a file of exactly 8 characters long (8.3 name). This situation was not checked, it is now fixed.
+    2008-02-01    improved (fat.c) filesearch routine for subdirectory support, it appears to work
+    2008-01-31    testing of subdirs
+    2008-01-25    added some extra output on the LCD contrast setting, when a user presses a button it shows on the serial port
+    2008-01-15    countfiles now show the user that it is counting files (message to display)
+                loading of carddirectory now displays the progressbar as it should, during loading you can clearly see the 3 different passes (notice the change in barspeed) this is caused by the fact that the number of files does not match the number of subdirectories and does not match the number of images (ie D64)
+    2008-01-12    fixed problem with root selection when using buttons (these routines required changes due to the added subdir functionality)
+                during selection using the buttons, the display uses a bar. This bar was a simple progress bar which is confusing as file selection has nothing to do with progress,
+                so this is now changed to sort of slider, like you may know from "modern" operating systems like Windows
+                Seekfileoncard return the file index (again)
+                Print_file_info routine has become obsolete, as this information is allready in the display (bottom right) in the form of the mode of operation
+                The directory is shown in 3 passes (pass-1=subdirs, pass-2=images, pass-3=files), the third pass shows filesize in blocks (as in any other directory)
+                Added the suggestions made by jussi, to the LCD routines for better LCD clone compatibillity
+    2008-01-11    restoring of the button functions, these functions required changes due to the added subdir functionality
+    2008-01-10    added countfiles routine (counting files can be usefull after all)
+    2008-01-08    Playing with subdirs (part...+2)
+                nu is er de uitzondering Root (index 0) maar eigenlijk is dit geen uitzondering.
+                Alle subdirs heben deze optie ook. index 0 betekent eigenlijk niets meer dan dat er geen D64 file geselecteerd is en dat we in de harddiskmode zitten
+    2008-01-07    Playing with subdirs (part...+1)
+    2008-01-05    Playing with subdirs (part...)
+    2008-01-04    The routine D64Directory is renamed to ImageDirectory, this because in the future not only D64 will be supported, by keeping all filetypes under the same directory routine, the software stays easy to read. But the name D64Directory is misleading if it reads more the D64's, so the name D64Directory is changed into ImageDirectory as it will show the contents of the image-file in directory style
+    2008-01-03    REQUIRES MANUAL CHANGE: the file pointer (when a directory is loaded is no longer a reference to the fileindex. since the fileindex principle has been dropped as it will be no longer practical when used in combination with subdirectories)
+    2008-01-02    removal of code that uses index number to refer to files
+                REQUIRES MANUAL CHANGE- it is no longer possible to use $0 bla bla bla for D64 file searches, although simple in use. It is no longer practical when files are stored in subdirs. It would take to long to scan the card after insertion and the filenumber would have to be 5 digits to address all possible files on a 1 GByte card
+    2007-12-26    counting the number of files on the card is a silly thing to do when we want to break open the 512 file barier by using subdirectories, so these routines are removed
+                the files are now displayed in groups when the carddirectory is loaded. Dir, D64, PRG-files this makes it easier to read (looks more organised as well (but's thats because its organised offcourse)
+                Sorting on alfabetical order is not going to happen as it would take too much memory or would be too time consuming
+    2007-12-23    added the routines to show a directory, the difficult part has yet to come... using these directories, something for the next few... weeks?!?!
+    2007-12-23    worked on directory formatting (i.o.w. the results caused by LOAD"$CARD"), now the directory width is different for the normal and the VIC20 mode (select by using the UI+ command to set the IEC speed)
+                when used in VIC-20 mode the directory width is limitted to 20 characters, so it displays nicely on a VIC-20
+                when used in normal mode the directory width is limitted to 28 characters, so that it holds the max amount of info, while being compatible with normal directory sizes
+                Every entry that needs to be loaded as a directory now is display with a proceeding $-sign.
+                This because the .PRG and .D64 files are no longer printed with their extension in the filename, but displayed as TYPE at the end of the line.
+                On a SX this might be a bit difficult to read (if you are in a hurry). By adding the $-sign, it becomes more clear how to load it AND
+                it saves the user the trouble of inserting the $-sign in the directory entry when he/she wants to load it.
+                Changed the search routine "SeekFileOnCard" in order to work with the longer filenames and to accept filenames without extensions
+    2007-12-21    worked on directory formatting (making sure that it looks OK after LOAD"$")
+                also created 2 different directory looks. A small look for the VIC20 and a normal look for others.
+                Also the VIC20 mode (25% higher IEC-speed is kept in EEPROM, so the user has to configure this only once as long as he/she uses a VIC20)
+                Simply use the standard UI- and UI+ commands to toggle between normal and VIC20 mode (see manual)
+    2007-12-20    worked on longfilenames
+    2007-12-19    now that longfilenames profe to be functional, let's apply them in the carddirecory routine(s)
+    2007-12-18    experimenting with FAT extra's (playing with longfilenames)
+    2007-10-27    a small change in LCD_nokia_3310.c (see it's history) solved the inverted character problem, now lines of inverted 
+                char look beter and the contrast is not disturbed. I expect that this would solve other contrast problem as well, 
+                there are people out there with LCD's that for some reason have a very "light" contrast and are difficult to read when
+                the display's content changes rapidly, it must be something likes this.
+    2007-10-25    removed the 1541-III SX detection as the 1541-III inside my SX is nothing more then a v1.0 upgraded to v1.1
+    2007-10-24    added the 1541-III dtv C64 edition to the list of recognized devices
+    2007-10-18    added the 1541-III second batch to the list of recognized devices
+    2007-10-17    added some extra features for hardware testing
+                when no card is inserted and the user pushes the i-button then the hardwaretestmenu is entered
+    2007-10-11    used the enum statement for the first time, it simplifies constant coding... a little
+    2007-08-15    still lot's of work to be done, but this version is suitable for beta-release... so release it!
+                people have been waiting long enough for a more stable release... so give it to them although it's not 100%
+                it IS better then the previous versions.
+    2007-06-30    added a mode of operation indicator, to show if we are operating in D64 mode or HD mode (root dir of card)
+                during button selection the progress-bar indicates where we are in the directory
+                during button selection some additional file information is shown on the third line
+    2007-06-28    small changes in display layout, moved index to error-line
+    2007-06-26    placed sample at seterrorcode. This is the best location because this requires only one place where the same sound can be connected to multiple error situations
+                display line-2 now shows the last error code (if not 0 or 73 (directly after reset))
+                the filename that is being loaded or saved is not displayed to the display any more (only visible via serial port)
+    2007-06-25    added the sound samples made by Willem K.(Thanks a lot Willem for your excellent work, unfortunatley the 
+                hardware does not allow it to play the samples to it's full quality, but the sounds are still very 
+                distinctive and recognisable as 1541 drive sounds)
+    2007-05-17    added a clear display line after the execution of LOAD, SAVE etc.
+    2007-05-15    the last few days have been spend with typing old listings from books to further test the current firmware
+    2007-05-10    the main do, while loop that checked for ATN was changed to a while(ATN... loop, that had a check for the release of the data line, this solved all my problems
+                set the delay to 1000uSec, no problems any more.    
+    2007-05-09    the new delay location and new value of 100uS was set back to 200uS (still at the new (better) location (the main loop)
+    2007-04-25    IEC_bus.c CheckForCommand had an delay of 200uS to ensure the "frame to release of ATN'-time" of min 20uS, this is removed and now in the higher level IEC staemachine (main.c)
+                the new location of this delay ensure a quicker response time when waiting for a command
+    2007-04-24    stared at the code tried to analyze what went wrong, failed to solve it
+    2007-04-23    IECUNDOTURNAROUND should not check on clock, corrected in IEC_bus.C
+    2007-04-21    demonstration of project at Maarssen, a very pleasant day. Learned that directories on the card make the 1541-III fail completely although it looks like it all works at first.
+                timing within the GET# handling is not 100% correct, adding some printf's for more info and suddenly there np problme no more, investigate further...
+    2007-04-18    added interrupt disabling within the datahandler, when the drive becomes a talker (caused by GET# statements) we must disable interrupts otherwise when the computer indicates the last GET# by pulling ATN low, we'd lock up because the interrupt pulls the data-line low and we still need to undo the turnaround (this was a tricky one, thank you my dear (DIY, 5Euro and self written visual basic software for windows PC's) PC logic analyzer
+    2007-04-15    removed the: print_device_status("              ");        this was the last statement of the openhandler, this statement should not be needed at this location in the code!
+                removed the: print_device_status("              ");        this was the last statement of the datahandler, this statement should not be needed at this location in the code!
+    ----------    Vacation @ Lommersbergen
+    2007-04-09    set the ATN interrupt filter value back to 25, tested with different values but 5 gives problems, 25 not, so we keep it at 25 (for now, keep this in mind, we need to get to the bottom of this someday)
+                note to myself: it apears that disabling of the buttons solves a lot of my problems, perhaps the AD conversion eats up so much time that it disturbs the IEC communication when it's not meant for us!
+    ATTENTION    improved readbuttons() routine, it now FIRST checks if a button is pressed and THEN checks which button, this saves a lot of conversion time when no button is pressed, this time becomes available to the statemachine which now can respond much faster to events
+            |    the LED RITHM blinking routines interfere with the IEC timing! DAMN! (those blinking routines I liked the most)
+             ->    LED RITHM routines removed (all that beautifull work for nothing). But what is the use of a beautifull blinking LED when it interferes with the IEC-bus...
+    2007-04-07    - Bugfix in FAT.C reported and fixed by Mattias Olsson
+                - Intensive trafic on a different device may cause the 1541-III to trigger false, disturbing the communication between the CBM computer and the other device
+                  Some additional checks are added to make sure that the 1541-III handles the UNTALK and UNLISTEN event ONLY when the 1541-III allready has left the IEC IDLE state
+    2007-04-05    added the function to readout the result of the opened buffer (GET#1, A$ directly after OPEN 1,8,2,"#")
+    2007-04-03    'fixed' bug in B-P command, it appeared that the real bug was in my BASIC program on my C64 (stupid typo regarding dev ID's,
+                so it worked on a real drive (8) but not on the 1541-III (9), if I had only swapped the devices to the other ID's the problem
+                would appread to be in the 1541 drive, which made it obvious that it was in the C64 program all along. But I had to find it
+                out the hard way (offcourse))
+    2007-04-02    worked on the same 'problem' again
+    2007-04-01    continue of the prev. day
+                the check IEC_CLOCK == 1 in UNDOTURNAROUND now has a time-out, simply to improve reliablillity... it helps a lot!
+                separated B-R and U1, since the first is 254 bytes and the second if the full 256 byte block-read
+                separated B-W and U2, since the first is 254 bytes and the second if the full 256 byte block-write
+    2007-03-31    data command (in IEC statemachine) now holds the check if the selected channel is opened, if the selected channel is not opened then the DATA command will be ignored (as it would on a normal drive)
+                testing and debugging the effects on the 1541-III when the C64 uses the GET# and INPUT# statement in a directory reading program that does not use the LOAD"$" syntax but U1 and B-P, the results are promissing, I'm on the right track...
+    2007-03-30    worked on the U1 and U2 command
+                added a buffer pointer to the D64blockread function and named this function D64blockread_new
+                added a buffer pointer to the D64blockwrite function and named this function D64blockwrite_new
+                replaced the code located under "errochannelhandler" under the openhandler (where it belongs)
+    2007-03-29    worked on the U1 and U2 command, these commands are handled in an identical way as the B-P command
+    2007-03-28    worked on the b-p command to get an idea of how the info is send towards the 1541 (this low level stuf is described nowhere and examples are very diverse, 
+                although the mean the same, it is very confusing to say the least. But it becomes more and more clearer everyday...)
+                Improved the routine "valuefromstring" so it can now scan for a number, the first character in the tested string does not has to be a number. This makes it more flexible to use.
+                Also this routine returns the input string with a pointer to the last location (so you know where to find the second number etc.)
+    2007-03-27    worked on the open command and the b-p command
+    2007-03-26    created the DOS_buffer and DOS_channel structures to hold all the required information
+    2007-03-25    complete rework on the open command and on the buffer definitions... I was wrong all along (damn...)
+                removed the independent BAM_buffer in order to use the DOS_buffer at buffer location #4 (DOS_buffer[4].buffer[..]) as you'd expect it to found as it was a real drive
+                replaced the variable Dos_buffer.status to NextAction in order to keep track of the next action of this device
+    2007-03-23    added more comments and worked on the openhandler (made some small progress, but lots of work to be done)
+    2007-03-22    added extra comments (over serial) for easier debugging of new code
+    2007-03-20    just staring at the code...
+    2007-03-18    worked on the channel handling, lots of work to do... but very important so it must be done, 
+                but it takes a lot of time before i will get it right, it's very confusing to implement (although
+                the concept is very clear and logical, the low level handling makes it complex and therefore 
+                confusing if not written down correctly the first time
+    2007-03-15    changed the blinking routines to use only green in the first batch of 1541-III's (they do not have a tri-color LED)
+                added filter on ATN-line, to prevent possible glitches from false triggering the ATN-interrupt
+    2007-03-12    Created the color cycle routine
+                Created a small blink at every transmitted/received block
+                The LED fade on and fade off function is discarded because it function as expected. 
+                The results are not worth the effort of coding the huge line of exeptions (fading leds are wanted at startup blabla but not during loading, 
+                you might miss an important event, it creates additional loading delays which are anoying with small files etc.)
+    2007-03-08    LED fade-on/off function, the LED does not go on and off its fades gently to the required state
+    2007-03-07    replaced the labels RITHM and normal by LED_RITHM and LED_ERROR which is the correct and non confusing label that it should be all along. The new colors are: on=green, error=red, rithm=green+red
+    2007-03-05    tri-color led support, for new batch 1541-III DTV a red/green LED has been added to compensate for the lack of a display
+    2007-01-30    ...
+    2007-01-25    started with the coding of the following commands: B-P:, U1: and U2:
+    2006-12-27    start of EEPROM read/write support, this will be finished when sequential file handling is supported, since the EEPROM is best to be handled as a seq. file
+    2006-12-06    release date of firmware version
+    2006-11-21    reworked improvement... now also the disk-ID is used (if given by user)
+                simplified the splitstring on comma, column and equal into one routine: splitstringon_sign, where the sign to 'split on' must be given
+    2006-11-20    improved formatting routine, now the diskname is actually used (if given by user)
+    2006-11-15    Added some extra print to serial port, so you don't need the display if you're connected to the serial port (can't see why, as a terminal is larger then a nokia display)
+                BUG:direct loading of a prg file from root does not seem to work any more !?!?! thought it was fixed
+                Fixed: caused by checking for FILE_PRESENT, which should be !=FALSE, because the new routine have more output then TRUE or FALSE
+    2006-11-13    Added contrast setting under iec command control: open15,device,15,"LCDCONTRAST=ddd";close15
+    2006-11-12    Implemented the copy function, there was allready a beginning for several weeks, but never really implemented until now.
+    2006-11-11    Sint Maarten, dus de bel gaat vaak...
+                Finished the routines and testing of the D64 file selection (directory loading) by name entry
+                I.o.w. instead of LOAD"$24",8 you can now specify the filename LOAD"$filename.D64" (where filename must be exactly 8 chars and for the lazy ones, just use the *-wildcard)
+                Setting of device ID using software is functional
+    2006-11-09    started with the D64 file selection by name (user request, because currently it is D64 file selection by index only)
+    2006-11-08    did some additional testing on the save situation where no card is present, but it apears that this is vitually not responding to the data. 
+                According to the logic analyser a real drive handles identical. This was not what I expected because this means that on a real drive and the 1541-III
+                when a user want to save data to a drive without a disk the user has to wait several seconds before the drive returns and then no confirmation is given until the errorchannel is read.
+    2006-11-07    added some extra checkpoints for card removal, there were some situations where the user could bypass the card removal checking routines, 
+                causing unexpected behavior. This is now fixed.
+    2006-11-06    did some testing on the load with and without card inserted
+    2006-11-05    BUG: when trying to load from device 10 (on a computer where nothing is connected as device-10, the 1541-III prevent the error "device not present"from happening
+                BUGFIX: the FREEIEC routine in combination with the disabling of the ATN-based interrupt solved the problem
+    2006-11-03    BUG: the "unsigned char index_cnt;" in "void CardDirectory(void)" prevented the user from using more then 255 files on a single card
+                BUGFIX:  "unsigned int index_cnt;", unfortunately I could not test this myself, since I could only store max. 247 files to my SD-card, strange, why !?!?! (they promissed me 512max.)
+                User request: added an extra space so that when more then 99files are stored on the card, the directory is still nicely aligned
+                BUG:loading of .PRG files does not seem to work when the whole filename is entered, 
+                but it does work when a part of the filename followed by a * is entered... curious, but true?
+                BUGFIX: the CBM computers do not recognize the '~'-sign and when printed to screen 
+                they show a pi-sign. Unfortunately, this sign cannot be entered during load/save.
+                so when doing this a 0xff value is substituted. Very unfortunate because this means
+                the comparison for the filenamesearch fails. By replacing the '~'-sign by the '/'-sign 
+                these problems are simply avoided and all works as intended.
+    2006-11-02    ALL routines are functional again, hurray for me, wahoo!!!
+    2006-11-02    making all 1541-III functions functional again as it was intended. So that you can use
+                OPEN 15,9,15,"S:blabla"
+                as well as:
+                OPEN 15,9,15
+                PRINT#15,"S:blabla"
+    2006-11-01    1541-III is functional again HURRAY !!!
+                New statemachine functions, the big difference between the new staemachine and the old one is basiccally that the old statemachine 
+                executed the open command BEFORE the UNLISTEN command, while the new statemachine executes the OPEN command AFTER the UNLISTEN 
+                command, this is a big difference, suddenly some mysterious delays that could not been found in the specs are not required any 
+                more. Suddenly it becomes clear that the strange delays were not neccessary after all as long as the proper statemachine was used.
+    2006-10-31    statemachine is better but not funcional yet... getting there
+    2006-10-30    fucked up the statemachine pretty bad... but it's the only way to build something better. Start with rebuilding it 
+                tomorrow (in the mean time I feel like crying and I am very glad that I made beackups of the previous version, just in case I can't put it back together)
+    2006-10-25    placed the LOAD routines in channel-0 (thats the location where these routine belong in the real 1541)
+                placed the SAVE routines in channel-0 (thats the location where these routine belong in the real 1541)
+                fixed serious bug in the seekfreeblock(D64_decoder.c), the routine could point to a free block inside track18, this is evil. This bug is fixed. Now a free block for saving purposes will never be allocated in track-18
+    2006-10-24    changed LOAD"$0" for LOAD"$CARD" and make the LOAD"$"=LOAD"$0" this should provide enough support for the Prophet64 to operate with the 1541-III
+                load and save routines are only avaiable under channel 0 and 1
+    2006-10-23    the errorchannel was threated as a single channel only used for error messages, but in fact it is used for much more... which I only started to realize when I tried to implement more commands that also used the channel 15 (errorchannel)
+                because of this it was possible to use the command :
+                OPEN 15,9,15,"N:blabla"
+                but not the command:
+                OPEN 15,9,15
+                PRINT#15,"N:blabla"
+                this is now fixed (both commands work) since the errorchannel is not only used for the handling of the errormessages
+    2006-10-21    timing selection possible by using the UI- and UI+ command. for the DTV users this is not required as timings are automatically set to the fastest possible value (as determined by Jussi S.)
+                .D64-file selection by using the command sequence: OPEN1,8,1,"$x":CLOSE1 Did not change the display of the 1541-III, this is fixed. No the D64 filename on the display is only changed when a new file is selected
+                changed the routine print_device_status(const unsigned char *message), it accepted only values that it decoded into a string, that was nonsens and creates only large unreradable code, now that is changed so it accepts constant strings
+                this also makes it easier to print the same line to the serial port (usefull if you don't have an LCD connected or want to log the actions)
+    2006-10-20    made a beginning in implementing the 'adjusted' IEC-bus timings for the DTV (also required for the faster VIC-20 mode (user-command UI-)
+    2006-10-16    replaced the '.' in the errorcode 73 for '-' which should be better regarding readabillity
+    2006-10-15    shortened the default errorcode by nine characters (removed 1541-III<space>), it now only shows the versionnumber of the software
+                added a new device-type 1541-III v1_1 (to indicate the second batch. Actually this is only a detail, since there is no real difference in the first and second batch.
+    2006-10-13    changed to MPLAB v7.40, did nothing else, was to busy handling pre-orders, packing 1541-III's and sticking address labels on the box...
+    2006-10-11    tested the use of deselectingt the card, this did not hep in reducing operating current, therefore no changes where made regrading the CS-line                    
+    2006-10-02    added the 1541-III DTV splash screen (so you can see if the correct system is detected, even if you have no terminal attached, well you have to have a display offcourse.... But if you do... it would really nice)
+                made also the definition for the SX version of the 1541-III... why? Because that's what this projects started, so if I come to the point of building the 1541-III into my SX then it at least has an appropriate startupscreen.
+    2006-10-01    added the autodetect routines (detect which PCB where dealing with, 1541-III or 1541-III dtv). This makes distribution of new firmware versions much easier. Also it is much clearer to the outside world to understand that the 1541-III and the 1541-III DTV use the same firmware, how do you explain to a non-technical user that the 1541-III and the DTV version use the same software if you cannot use the same hex-file...
+    2006-09-13    when browsing through my 1541-II user's guide I found a different replcae command then I (assumed was correct) found in the "werken met de commodore disk drive" book (R0:<newname>=0:<oldname>). Changed it into the version the 1541-II manual describes (R0:<newname>=<oldname>)
+                the replace command functions very well regarding the highscore of Int. Karate, but for some reason Commando cannot read back the highscore svaed by the same routines, after loading highscore the program crashes
+    2006-09-12    REPLACE-command (combination of SCRATCH and SAVE), tested it and it works, commando does not work with it ?!?!? further testing required
+    2006-09-11    RENAME-command is functional
+                scratch command now includes the correct error handling, the error-code 1 shows the number of files scratched in the last track value
+    2006-09-10    scratch function nows also includes the use of wildcards (identical to file-loading wildcards)
+                also an harmless bug was found, 'the 16th char of each dir entry was not printed when the directory was loaded' (<15 should have been <16) FIXED
+    2006-09-05    fixed a small directory problem which made the first file invisible, this was OK but due to the introduction of the new routines a small thinking error was made. 
+    2006-09-04    a small step further with write support
+    2006-09-03    spend all day searching for a bug that wasn't there. The 1541-III behaved strange after I modified my code heavily. It looked like a pointer problem, But no such problem was in my code. At the end it was clear, my 1541-II was switched off and caused erratic behaviour on the bus, resetting my 1541-III at the strangest moments
+    2006-09-02    added struct for each directory entry and changed the directory loading routines so that the use the new and simplified block read routines
+                also now all large buffers are defined in main.c (cause there is where you want to keep an overview of your resources
+    2006-08-31    moved all low level D64 acces routines to: D64_decoder.c
+    2006-08-30    created the BLOCK-WRITE routine, which is actually a very simple command, just dump some data to the D64 (only read the 512 block, change 256bytes then write back)
+                created the BLOCK-READ routine, which is even easier then BLOCK-WRITE
+                created the BLOCK-ALLOCATE routine,...
+                created the BLOCK-FREE routine,...
+                The actual command using the above routines still has to be written... (so much to do in so little time)
+    2006-08-28    added the testing function 'n:' this function tests the block write to card routine
+                so now we can format a d64 according to default settings, this only works for the smallest D64 files, other files will NOT be reset completely, thats why this command is for testing only!!!
+    2006-08-23    some cards had problems, it apears that these cards where not functioning according specs, read the whole story in the file:ata.c
+                improved filefilter routines and combined them into one single routine, this makes the software easier to maintain
+                simplified some areas of the code thanks to the Lcd_CharBold() function, saves a lot of putch(...)
+    2006-08-21    added more debugging info in order to find the problem regarding the problems with some card not being supported...
+    2006-08-17    improved contrast setting button response. The firmware version is now shown on the display when no card is inserted (was allready shown on the serial port at startup but normally this option is never used (only for firmware upgrades))
+    2006-08-16    the contrast settings are now stored in EEPROM, so you configure it only once and use it forever without the need of changing it again at every startup
+    2006-08-15    added subroutines to set the displays contrast, very important since there seems to be some slight difference between the old and new types of display
+                contrast can only be changed when no card is inserted !!!
+    2006-08-12    added PWM-output on RB3, this for future support of speaker (thinks of clicks on every track change, disk swap, buttonpress etc.) Now at power-up or reset it plays "halleluj.wav", as a small easter egg since nobody is informed about this feature.
+    2006-07-09    changed the read file statemachine, now the read is combined with write, since the command sequence is allmost identical
+                corrected the file-locked indicator (it was printed BEFORE the filetype while it should be printed AFTER... silly me)
+                track & sector values print to display routine were printed after loading of the block, it is better to print BEFORE loading cause this makes more sense
+                added an extra print track and sector routine to properly display the last track and sector of the loaded file
+                routine 'Count_files_on_card' only counted the D64 files but it should count ALL files, otherwise you can have an indexnumber higher then the 'number of files on card', that would look stupid!
+                removed stupid, stupid, stupid little BUG which prevented the second-last byte from being transferred during load, causing some files to fail after loading
+    2006-07-05    improved start-up behaviour, now the 1541-III does not 'hang-up' when accessed without card (basically removal of some busyloops
+                added textual message 'LOADING' to the loading related actions (SAVING, DELETING etc. is offcourse to be expected)
+    2006-07-04    changed release version number into release version data (thats easier to track changes in the history, you never know...)
+    2006-07-03    buttons, functions great, you cannot select a non D64 file
+                detection of card removal during operation
+    2006-07-02    added functional button selection, but it functions only once?!?!
+                added a simple retry mechanism in 'Init_Card_SPI'
+    2006-06-30    fixed silly bug in card detect & write protect detection routines
+    2006-06-27    changed the ADC registers to the correct 18F2620 ADC registers settings (the 18F2620 has not 2 but 3 regsiters)
+    2006-06-23    changed the device to 18F2620 (the prototype device was 18252 the 2620 can do MUCH more for allmost the same price)
+                removed the small demo-sequence
+    2006-05-20    hacked in a small demo-sequence for the next HCC-meeting in Maarsen, this for use on the "poormans 4K-pixel beamer"
+    2006-04-20    improvement in startup screen, now the splash screen stays partially visible exposing only the 1541-III logo (nice)
+    2006-04-12    implementation of the ATN under interrupt, this is required for future routine (like file selection using buttons)    2006-04-03    added splash screen at power-up
+                ATN under interrupt has the advantage that the computer is confirmed that the device is present while being busy with other things, now we do not have to leave every loop within 1mS or except 'device not present', it is all handled in the interrupt (hurray!!)
+    2006-04-02    added extra display functionality, like a progress bar (for loading and saving)
+    2006-03-31    2nd day of testing the nokia 3310 lcd, it works
+    2006-02-28    some modifications required for the new PCB design and some testing routines
+    2006-03-13    when the user tries to acces a directory that is not there, future actions will refer to the card.
+    2006-03-10    the file not found problem solved, I needed to release the bus, hurray. Attila, thanks for the information, really appreciate it
+    2006-02-22    added frame_handshake signal for later use (trying to solve the file not found situation)
+    2006-02-20  Loading of .PRG files is now possible, the search routine will check the filename up to the first 8 chars
+                Preparing INT0 for interrupt handling of the ATN-line
+    2006-02-19  Loading of .PRG files from the ROOT of the MMC/SD-card is now possible, still have the program the file search routine, it now only recognizes the * wildcard
+    2006-02-18    Today was the day of the big presentation at Commdore GG in Maarsen. Well.. it was not exactly a big presentation. But the interest for this project exceeded my wildest dreams. A giant motivation boost!!
+                preparing code for the loading of .PRG file from the root directory, this may be usefull for loading a special start-up program for exploring the MMC/SD-card or whatever (it's a 'future' user request)
+    2006-2-9/17    Nothing, code is stable now, do nothing untill the presentation at commodore GG has passed
+    2006-02-08    added a routine 'print_D64_TSB' to make sure that the same things (Track Sector Blocks) are printed in the same manor
+                added the DOT in the 8.3 filename representation in the 'card directory' routine, also added an extra space for better alligment
+    2006-02-07    added file selection directly (and only) after reset
+                also added a routine 'print_D64_name' to make sure the same things (filename) are printed in the same manor (the best way to achieve this is by a single routine)
+    2006-02-05    added LED blinking codes to the existing error messages
+    2006-02-04    added interrupt routines to realise the LED blinking (req. for the original LED blinking error indicators)
+    2006-02-03  implemented filter on filesize and extension, this means only D64 files are shown (command: LOAD"$0",DEVICE)
+    2006-02-02    improvements in code layout... i.o.w. making it more readable, fixed some FAT bugs, tremendous speed improvement !!!
+                Benchmark results:    |     filename         | #blocks |    1541-II  | 1541-III | Conclusion
+                --------------------+-------------------+---------+----------+----------+----------------
+                                       |  Flimbo's Quest   |   172   |   1:42   |   1:20   | (78% of the time req. by a real 1541, i.o.w. this drives operates at 127,5% of the speed of a real 1541)
+                                       |                   |         |          |          |
+
+    2006-01-29  Removal of the redundant block_buffer and dat_buf registers, as a result of better 'fat' and 'ata' routines                           
+    2006-01-26    Loading of deleted files was possible, this is now fixed            
+    2006-01-22    Adjusted the 'help' section in the $0 (card directory) for proper reading on a VC-20                                                  
+    2006-01-20  it appeared that the presence of a real 1541-II on the bus, creates the situation where some delays are not required. Make sure we test WITH AND WITHOUT other devices on the bus !!! A 100uS delay is required after det. of the first checkforcommand in our 'statemachine'                                               
+    2006-01-19    removed unnecessary PRINTF's, added printf filename near LOADD64FILE
+    2006-01-19  fixed ValueFromString bug (didn't clear the variable, worked 1 time) fixed directory loading bug (it failed LOAD"$1",9 but not the rest) 
+    2006-01-18    finished send-error-code routine (although Track and Sector are still hardcoded to 0                                                
+    2006-01-16    still searching for problem of the previous day... found the problem was in the release of the bus, fixed in unlisten with FREEIEC routine.                                               
+    2006-01-15  continued search for the 'loadin works only the first time' problem 
+    2006-01-12    renamed some routines, rewritten part of the statemachine            
+    2006-01-11    rewritten the main decoder loop (statemachine)                        
+    2006-01-10    TALK and LISTEN definitions were mixed up, is corrected    improved the FreeIEC routine                                        
+    2006-01-09    interference problem with other devices on the bus has been solved    
+    2006-01-04    better command decoder                                              
+    2006-01-02    begining of real/serious command decoder                            
+    2006-01-01    corrected small error in directory, now text allignment is correct  
+    2005-12-24  implementation of the actual directory of an D64 emulator file        
+    2005-12-22  fixed the directory, now we can load a dir into the C64             
+    2005-12-18  testing of the IEC-write and TurnAround routines                    
+    2005-10/12  gathering data about the IEC-bus, build a logic ananlyser to monitor the IEC-bus activity of a real C64 and 1541-II                      
+    2005-09-20    raw design of fileselection routine                                 
+    2005-09-21    design of ADC button decoder                                        
+    2005-09-22    design of user interface                                            
+    2005-09-26    figured out how to read the disks name from the correct track sector
+    2005-09-02    figured out how to decode the ImageDirectory, file by file, algoRITHM    
+    2005-09-02  started with the free sectors routine                               
+*/
+
+/*  TO DO:                                                                          
+    ------      
+
+    for specific "to do" (pieces of missing code) use the following keyword (use search function of editor): 
+    //to do:
+
+    -replace D64blockread functioncall(s) for D64blockread_new and discard the D64blockread, then rename the D64blockread_new to D64blockread
+    -replace D64blockwrite functioncall(s) for D64blockwrite_new and discard the D64blockwrite, then rename the D64blockwrite_new to D64blockwrite
+
+    - the index number can only display 999 entries, theorectically a 2GB card can store 11000 entries (spread over several directories and in 8.3 to save space)
+      so there are two options... leave out the index number or enlarge the indexnumber to 5 digits instead of 3
+
+    - controleren of er nog (andere) plekken zijn waar "extractfilenamefromstring" gebruikt kan worden
+    - controleren of er nog op plaatsen gebruik word gemaakt van IEC_undoturnaround, dit zou IEC_letgo moeten zijn simpelweg omdat undo_turnaround niet gedefinieerd is in de IEC specs
+
+    - hoe zit het met de 1541-III dtv in de versie met de tri-color LED, zit daar ook een condensator aan de ingang om te detetcteren dat het een andere versie is?
+
+    - loading of a directory without typeing LOAD"$",8 (zie de boeken voor voorbeeld programma's)
+    - block read and write... B-W en B-R, deze zijn nu nog voor de 256byte maar moeten uiteraard voor de 254 byte versie zijn, de 1e twee bytes overslaan !?!?
+
+    - the 1541-III fails to function in combination with a C128
+
+    - the routine "void SendErrorMessage(void)" is designed to transmit ALL 4 values(byte,byte,string,byte) of the error message, but what if a user request only the first(byte), how is this handled by a real 1541?
+      check for EOI bij elke stap
+
+    - Make note in manual about unrecognised characters (see bugfix of 2006-11-03)
+
+    - support for eror-bytes in extended 35- and 40-track .D64 files
+*/
+
+/*    Notes to myself:
+    ----------------
+    -C128 problem NOT 1541-III: CAN'T LOAD OUTRUN.PRG ANY MORE IF LOADED CBM CRASHES!!!    THE ABOVE IS CAUSED SIMPLY BECAUSE THIS FILE FAILS TO FUNCTION ON MY C128 ON WHICH I TEST MOSTLY. IT FUNCTIONS PERFECTLY ON MY C64
+
+    -when teh C64 screen is "blanked" it should be possible to adjust the timings from 60uS to 20uS, since the VIC is not interfering (or doesn't it work like this)
+
+*/
+
+/*----------------------------------------------------------------------------------*/
+
+// example of sd card access
+#include "mbed.h"
+// #include "string"
+// #include "SDHCFileSystem.h"
+// 
+// SDFileSystem sd(p5, p6, p7, p8, "sd"); // mosi, miso, sclk, cs
+//   
+// int main() {
+//       
+//       FILE *fp = fopen("/sd/myfile.txt", "w");
+//       fprintf(fp, "\n\rHello World!\n\r");
+//       fclose(fp);
+// }
+ // IEC hardware connections
+DigitalInOut nSRQ(p18);     // DIN6 pin 1
+DigitalInOut nATN(p17);     // DIN6 pin 3
+DigitalInOut nCLK(p16);     // DIN6 pin 4
+DigitalInOut nDATA(p15);    // DIN6 pin 5
+DigitalInOut nRESET(p19);   // DIN6 pin 6
+           
+InterruptIn nIRQ(p30);      // external loop: connect to nATN
+           
+DigitalIn JUMPER_J2(p21);
+DigitalIn JUMPER_J3(p22);
+
+DigitalOut myled1(LED1);
+DigitalOut myled2(LED2);
+DigitalOut myled3(LED3);
+DigitalOut myled4(LED4);
+                             
+#define LED_GREEN myled1
+#define LED_RED   myled2
+
+Timer timeout;
+Serial linktopc(USBTX,USBRX);
+
+// #define IEC_ATN_REL()    IEC_DDR &= ~IEC_BIT_ATN
+void IEC_ATN_REL() {
+    nATN=1;
+    nATN.input();
+}
+
+// #define IEC_ATN_PULL()   IEC_DDR |= IEC_BIT_ATN
+void IEC_ATN_PULL() {
+    nATN.output();
+    nATN=0;
+}
+
+// #define IEC_CLOCK_REL()  IEC_DDR &= ~IEC_BIT_CLOCK
+void IEC_CLOCK_REL() {
+    nCLK=1;
+    nCLK.input();
+}
+
+// #define IEC_CLOCK_PULL() IEC_DDR |= IEC_BIT_CLOCK
+void IEC_CLOCK_PULL() {
+    nCLK.output();
+    nCLK=0;
+}
+
+// #define IEC_DATA_REL()   IEC_DDR &= ~IEC_BIT_DATA
+void IEC_DATA_REL() {
+    nDATA=1;
+    nDATA.input();
+}
+
+// #define IEC_DATA_PULL()  IEC_DDR |= IEC_BIT_DATA
+void IEC_DATA_PULL() {
+    nDATA.output();
+    nDATA=0;
+}
+
+int IEC_ATN() {
+    nATN.input();
+    return    nATN;
+}
+
+int IEC_CLOCK() {
+    nCLK.input();
+    return  nCLK;
+}
+
+int IEC_DATA() {
+    nDATA.input();
+    return   nDATA;
+}
+
+
+
+/*--------------------------------------------------------*/
+/*                        includes                        */
+/*--------------------------------------------------------*/
+#include <mbed.h>
+
+// #include <stdio.h>
+// #include <stdlib.h>
+// #include <string.h>
+// #include <math.h>
+#include <main.h>
+#include <hardware.h>
+#include <delay.h>
+#include <ata.h>
+#include <fat.h>
+#include <D64_decoder.h>
+#include <T64_decoder.h>
+#include <IEC_bus.h>
+
+/*--------------------------------------------------------*/
+/*                       EEPROM                           */
+/*--------------------------------------------------------*/
+/*
+__EEPROM_DATA('-','-','-','-','-','-','-','-');
+__EEPROM_DATA('-','-','-','-','-','-','-','-');
+__EEPROM_DATA('-','-','-','-','-','-','-','-');
+__EEPROM_DATA('-','-','-','-','-','-','-','-');
+__EEPROM_DATA('-','-','-','-','-','-','-','-');
+*/
+/*--------------------------------------------------------*/
+
+/*--------------------------------------------------------*/
+/*                        constants                       */   
+/*--------------------------------------------------------*/
+
+#define            FALSE                0            /*FALSE*/
+#define            TRUE                1            /*TRUE*/
+
+/*--------------------------------------------------------*/
+
+/*PCB types and versions*/
+enum PCBTYPE{v1=10, v1_1, DTV, DTV_C64};
+
+/*defines for the IEC-bus statemachine*/
+enum IEC_bus_statemachine{IDLE=0, ACTIVE_LISTEN, ACTIVE_TALK};
+
+/*blink modes*/
+enum LED_modes{LED_OFF=0, LED_ON, LED_ERROR, LED_GR, LED_RD, LED_OR};
+
+/*disk-state*/
+enum DiskState{NO_CARD=0, CARD_ACTIVE, INVALID_POINTER};
+
+/*1541-III commands*/
+enum Commandset{ABORT=0, ABORT_SENDING, ABORT_RECEIVING, NO_FILE, FILE_OPEN, NEW_D64, CARD_DIRECTORY, DIRECTORY, RD_FILE, RD_FILE_FROM_ROOT, WR_FILE, WR_FILE_TO_ROOT, REPLACE_FILE, SCRATCH_FILE, RENAME_FILE, COPY_FILE, SET_DEVICEADDR, USER_IEC_SPD_UP, USER_IEC_SPD_DWN, MODIFY_FILE, MODIFY_FILE_TO_ROOT};
+
+/*filetypes*/
+enum Filetypes{SEQUENTIAL=1, RELATIVE, PROGRAM, USER, LENGTH};
+
+/*--------------------------------------------------------*/
+
+#define            BUTTON_SELECTION_RATE 350        /*this value determines the button repetition rate*/
+
+/*MMC/SD-card*/
+#define            MMCCARD                2            /*card type found reference*/
+#define            SDCARD                3            /*card type found reference*/            
+#define            FILENOTFOUND         4            /*filenotfound reference*/
+#define            SUPPVOLT            0x3C        /*mask and compare value for cards that support 3.0-3.1, 3.1-3.2, 3.2-3.3, 3.3-3.4 Volt*/
+
+/*buttons*/
+#define            button_none            0            /*numerical value of ADC when no button is pressed*/
+#define            button_tolerance    15            /*max. alowable deviation of expected button values*/
+#define            button_1             870            /*numerical value of ADC when button-1 is pressed*/
+#define            button_2            721            /*numerical value of ADC when button-2 is pressed*/
+#define            button_3            575            /*numerical value of ADC when button-3 is pressed*/
+#define            button_4            431            /*numerical value of ADC when button-4 is pressed*/
+#define            button_5             288            /*numerical value of ADC when button-5 is pressed*/
+#define            button_6            145            /*numerical value of ADC when button-6 is pressed*/
+
+/*1541-III operational modes/filefilter results*/
+#define            NONE                0        /*the 1541-III has currently no file selected. I.o.w. the 1541-III works in the root directory and can load files directly from the card*/
+#define            PRG_FILE            1
+#define            D64_35T_MODE        2        /*the 1541-III has opened a .D64 file (35 tracks no errors) and works as of your working with a real 1541 disk drive*/
+#define            D64_35T_ER_MODE        3        /*the 1541-III has opened a .D64 file (35 tracks with errors) and works as of your working with a real 1541 disk drive*/
+#define            D64_40T_MODE        4        /*the 1541-III has opened a .D64 file (40 tracks no errors) and works as of your working with a real 1541 disk drive*/
+#define            D64_40T_ER_MODE        5        /*the 1541-III has opened a .D64 file (40 tracks with errors) and works as of your working with a real 1541 disk drive*/
+#define            T64_MODE            6        /*the 1541-III has opened a .T64 file*/
+#define            SUBDIRECTORY        100        /*the 1541-III has encountered a subdirectory*/
+#define            UNKNOWN                255        /*the 1541-III has encountered a file that has no extension*/
+
+#define            FILE_NOT_PRESENT    0
+#define            FILE_PRESENT        1
+
+/*text printing definitions*/
+#define            PLAIN                0
+#define            BOLD                1
+#define            INVERTED            2
+
+/*--------------------------------------------------------*/
+/*                         macro's                        */
+/*--------------------------------------------------------*/
+#define            disable()     GIE=0                /*disable interrupts*/
+#define            enable()     GIE=1                /*enable interrupts*/
+
+/*--------------------------------------------------------*/
+/*                         globals                        */
+/*--------------------------------------------------------*/
+
+unsigned char    RAM_buffer[256];            /*this is the buffer capable of holding one 256 byte block, a memory area to which the user or the 1541-III can write/read data to/from*/
+//unsigned char    BAM_buffer[162];            /*this buffer holds the Block Allocation Map, required for when we want to write to the D64 (max 40 tracks)*/
+unsigned char     block_buffer[512];            /*this buffers the data 'as read from' or 'to be written to' the card*/
+struct            DOS_buffer_struct    DOS_buffer[MAX_NUMBER_OF_DOS_BUFFERS];    /*this array of structs holds the information about the possible channels*/
+struct            DOS_channel_struct    DOS_channel[16];                        /*this array of structs holds this information about the currently used channels*/
+
+/*--------------------------------------------------------*/
+unsigned char     PCB_type;                    /*this value contains the PCB type/version*/
+unsigned int    PCB_type_timer;                /*this timer determines the actual PCB type detection*/
+unsigned char    setting_contrast;            /*this is the value belonging to the contrast setting as found in EEPROM*/
+unsigned char    VIC20_mode;                    /*this is the value belonging to the IEC-speed setting as found in EEPROM*/
+
+unsigned char    devicenumber;                /*this var. holds the device number 8,9,10 or 11*/
+unsigned char    device_command;
+
+unsigned char    IEC_state;                    /*talk, listen or idle*/
+unsigned char    channel;                    /*this register holds the channel value*/
+unsigned char    nextfreebuffer;                /*this register holds the buffernumber of the next buffer to be used*/
+unsigned char    ChannelUsesBuffer[16];        /*small array to keep track of which channel uses what buffer (to drive you mad... MAD I SAY!$#%$#%$#$%#)*/
+unsigned char    command;                    /*this is the unfiltered (as received for the IEC-bus) command*/
+unsigned char    command_string[41];            /*this string holds the command details/options*/
+unsigned char    filename_string[41];        /*this string (is suppost to) hold(s) the filename*/
+unsigned char    oldfilename_string[41];        /*this string (is suppost to) hold(s) the new filename (for renaming routines)*/
+unsigned char    value_string[17];            /*this string (is suppost to) hold(s) a value*/
+unsigned char    string_pntr;
+unsigned char    string_pntr_2;
+unsigned long    value_long;
+unsigned char    value_1;
+unsigned char    value_2;
+unsigned char    value_3;
+unsigned char    value_4;
+unsigned char    filetype_string[41];        /*filetype can be sequential, program, user, etc.*/
+unsigned char    RW_string[41];                /*file read or write*/
+
+unsigned char    error_code = 73;            /*this holds the error-message generated by one of the disk routines*/
+unsigned char    LastTrack = 0;                /*last accessed track variable*/
+unsigned char    LastSector = 0;                /*last accessed sector variable*/
+unsigned char    files_scratched = 0;        /**/
+
+unsigned char    Response_data[5];
+
+unsigned char    file_type;                    /*this holds the type of the current file or NONE if no file is selected*/        
+unsigned int    file_number;                /*the current file index number, this number is used as a reference for button actions*/
+unsigned int    CountedFiles;                /*the number of files in the current (root/sub)-directory*/
+
+struct             file2TYPE             file;        /*file handle*/
+struct            directory_entry        dir_entry;    /*directory structure inside the D64*/
+
+bit                button_prev;
+bit                button_select;
+bit                button_next;
+
+unsigned char    Blink_mode;                    /*mode of operation of the blink routine*/
+bit                Blink_dir;                    /*direction of intensity change (up or down)*/
+unsigned char    Blink_block;                /*holds the byte-number on which the LED should go off in order to create a blink at every block*/
+unsigned char    LED_OFF_delay;                /*holds the delay timing value for the LED-OFF time*/
+bit                LED_status;                    /*the current state of the LED is stored here*/
+unsigned char    LED_color;                    /*value to keep track of current LED-color*/
+unsigned char    next_LED_color;                /*value to keep track of current LED-color*/
+unsigned char    DiskState;                    /*state of the disk (image) inside the drive (1541-III)*/
+
+bit             EOI;                        /*End Of Indicator: this flag (when TRUE) indicates that the last byte is being transmitted or received*/
+bit             TimeOut;                    /*Timeout-flag*/
+
+unsigned char     dirtrack, dirsector, direntry;
+unsigned long    lp, lp2;
+unsigned int    blocksize;
+unsigned char    track, sector;
+unsigned char    file_status;
+
+/*--------------------------------------------------------*/
+/*                     local functions                    */
+/*--------------------------------------------------------*/
+void WaitForString(unsigned char *outputstring, unsigned frame_handshake);
+unsigned char ValueFromString(unsigned char *inputstring, unsigned char *outputvalue);
+unsigned char LongValueFromString(unsigned char *inputstring, unsigned long *outputvalue);
+void ExtractFilenameFromString(unsigned char *input_string, unsigned char *output_string);
+unsigned char SplitStringOn_Sign(unsigned char sign, unsigned char *beforesign_string, unsigned char *aftersign_string);
+
+void IEC_direction_statemachine(void);
+void OpenHandler(void);
+void DataHandler(void);
+void AutoDetectPcbType(void);
+void NoCardMenu(void);
+void HardWareTestMenu(void);
+unsigned char CardStatus(void);
+void CountFiles(void);
+unsigned char Init_Card_SPI(void);
+unsigned char FileFilter(void);
+
+unsigned char SearchFreeBuffer(void);
+
+void Clear_block_buffer(void);
+void SelectD64Image(void);
+void CardDirectory(void);
+void D64Directory(void);
+void T64Directory(void);
+unsigned int SeekFileOnCard(unsigned char *filename, struct file2TYPE *file);
+void LoadFileFromCard(struct file2TYPE *file);
+void LoadD64File(unsigned char trk, unsigned char sec, unsigned int filesizeinblocks);
+unsigned char SaveD64File(void);
+unsigned char CopyD64File(unsigned char trk, unsigned char sec, unsigned int filesizeinblocks);
+
+void SetErrorCode(unsigned char error, unsigned char LEDmode);
+void SendErrorMessage(void);
+
+void print_device_status(const unsigned char *message);
+void print_D64_name(unsigned char mode);
+void print_D64_TSB(unsigned char trk, unsigned char sec, unsigned int blk, unsigned int total_blk);
+
+unsigned char ReadDeviceJumper(void);
+unsigned char ReadButtons(void);
+
+void FormatD64File(unsigned char *diskname, unsigned char *diskid);
+/*****************************************************************************************************************/
+/*****************************************************************************************************************/
+/*****************************************************************************************************************/
+/*Interrupt service routines*/
+/*****************************************************************************************************************/
+/*****************************************************************************************************************/
+/*Low-priority interrupt entry point*/
+void NotTimeCritical(void)
+{
+
+}
+
+/*High-priority interrupt entry point*/
+void high_priority(void)
+{
+    unsigned char    filter_cnt;
+    /*By putting the ATN-line detection on an interrupt-line we detect the ATN-situation independent of*/
+    /*other actions, like selecting a new D64 image. This method makes IEC programming less complex*/
+    /*the small filter also creates a hold-off time, for some reason this is required*/
+        filter_cnt = 25;            /*check the ATN line it must be kept low for a few cycles at least otherwise it might have been a glitch*/
+        while(IEC_ATN() == 0)            /*although this filter does add some latency to the start of a data transfer, it is not noticeable in practice*/
+        {              
+                          /*it does however add a more secure ATN-line detection, since the inputlines are not filtered in any other way*/
+            wait_us(1);
+            filter_cnt--;
+            if (filter_cnt == 0)    /*when the ATN signal has been proven not to be a glitch*/
+            {                        /*we can safely handle the ATN-signal*/        
+                IEC_DATA_PULL();/*join the bus...*/
+                    myled3=1;
+
+                break;
+            }
+        }
+}
+
+/*macro*/
+// #define        disable_ATN_interrupt()    INT0IE = 0    /*disable interrupts on ATN line*/
+// #define        enable_ATN_interrupt()    INT0IE = 1    /*enable interrupts on ATN line*/
+
+void enable_ATN_interrupt(){
+    nIRQ.fall(&high_priority);
+}
+
+void disable_ATN_interrupt(){
+        nIRQ.fall(NULL);
+}
+/*****************************************************************************************************************/
+/*****************************************************************************************************************/
+/*Main*/
+/*****************************************************************************************************************/
+/*****************************************************************************************************************/
+
+int main(void)
+{
+
+    HardwareInit();                                    /*init controller registers and I/O-lines*/
+//    GetSettingsFromEEPROM();                        /*read EEPROM settings*/
+    devicenumber = ReadDeviceJumper();                /*read the devicenumber jumper*/
+    InitIEC();                                        /*initialize the IEC-bus levels*/
+                       /*initialize SPI*/
+
+
+    linktopc.baud(115200);
+
+    timeout.start();     // start timer
+    
+ //   InitLcd();                                        /*initialize the LCD*/
+    AutoDetectPcbType();                            /*measure the button capacitor to determine PCB type*/
+    OutputToRS232();                                /*set standard output to RS232*/
+    printf("\r\n  -----------------------------------------");
+    printf("\r\n |                                         |");
+    printf("\r\n |                                         |");
+    printf("\r\n |        --==   1541 - III    ==--        |");
+    printf("\r\n |             (by J.Derogee)              |");
+    printf("\r\n |      (http://jderogee.tripod.com)       |");
+    printf("\r\n |                                         |");
+    printf("\r\n |                                         |");
+    printf("\r\n |                                         |");
+    printf("\r\n |                                         |");
+    printf("\r\n |                                         |");
+    printf("\r\n |                                         |");
+    printf("\r\n |                                         |");
+    printf("\r\n |                                         |");
+    printf("\r\n |                                         |");
+    printf("\r\n |                                         |");
+    printf("\r\n |     --------------------------------    |");
+    printf("\r\n | ( ) |Firmware vers.: v20%02d-%02d-%02d   |    |",RELEASE_VERSION,RELEASE_VERSION_SUB,RELEASE_VERSION_SUB_SUB);
+    printf("\r\n |     |J2 (Device-ID): ID=%1d          |    |",devicenumber);
+    printf("\r\n |     |J3 (Bootldr)  : ");
+    if (JUMPER_J3 == 0)
+        printf("ACTIVE        |    |");        
+    else
+        printf("DISABLED      |    |");        
+
+    printf("\r\n | ( ) |Contrast      : 0x%02x          |    |",setting_contrast);    /*show the settings*/    
+    printf("\r\n |     |VIC20-mode    : ");
+    if (VIC20_mode == TRUE)
+        printf("TRUE          |    |");        
+    else
+        printf("FALSE         |    |");        
+
+    printf("\r\n |     |PCB type det. : %05d         |    |",PCB_type_timer);    /*check which kind of PCb we are dealing with...*/    
+
+    /*adjust the startup sequence accordingly and settings depending on the PCB version*/
+    if (PCB_type == v1)
+    {
+        printf("\r\n | ( ) |Detected PCB  : 1541-III v1.0 |    |");
+//        Lcd_show_1541_III();                        /*show splash screen*/
+        SetIEC_timings(TIMINGS_DEFAULT);            /*set timings to default*/
+        Blink_block = 235;                            /*i.e. set the value to 225 to get a short off-time (it count to 254 and then goes on again), set value to 255 and it never blinks*/
+    }
+
+    if (PCB_type == v1_1)
+    {
+        printf("\r\n | ( ) |Detected PCB  : 1541-III v1.1 |    |");
+  //      Lcd_show_1541_III();                        /*show splash screen*/
+        SetIEC_timings(TIMINGS_DEFAULT);            /*set timings to default*/
+        Blink_block = 235;                            /*i.e. set the value to 225 to get a short off-time (it count to 254 and then goes on again), set value to 255 and it never blinks*/
+    }
+
+    if (PCB_type == DTV)
+    {
+        printf("\r\n | ( ) |Detected PCB  : 1541-III DTV  |    |");
+    //    Lcd_show_1541_III_DTV();                    /*show splash screen*/
+        SetIEC_timings(TIMINGS_DTV);                /*set timings according the settings as requested by Jussi (DTV tested settings)*/
+        Blink_block = 235;                            /*i.e. set the value to 225 to get a short off-time (it count to 254 and then goes on again), set value to 255 and it never blinks*/
+    }
+
+    if (PCB_type == DTV_C64)
+    {
+        printf("\r\n | ( ) |Detected PCB : 1541-III DTV   |    |");
+      //  Lcd_show_1541_III_DTV();                     /*show splash screen*/
+        SetIEC_timings(TIMINGS_DEFAULT);             /*set default timings */
+        Blink_block = 235; 
+    }
+
+    printf("\r\n |     --------------------------------    |");
+    printf("\r\n |                                         |");
+    printf("\r\n |     O                             O     |");
+    printf("\r\n |   POWER                         DRIVE   |");
+    printf("\r\n |                                         |");
+    printf("\r\n  -----------------------------------------");
+    printf("\r\n");
+
+    if (VIC20_mode == TRUE)                            /*when the user has selected the VIC20 mode, respect that setting and use it again. This is more userfriedly then setting it every time the system start/resets*/
+        SetIEC_timings(TIMINGS_VIC20);                /*the VIC20_mode is not only a speed setting. It is a mode where the card directory is adjusted for a smaller (24 instead of 40 columns) screen*/
+                                                    /*set timings according the VIC-20 settings (25% faster mode)*/
+
+    printf("\r\n");                                    /*set cursor to the beginning of the next line (prepare for future (optional) debug printing)*/
+    OutputToLCD();                                    /*set standard output to LCD*/
+    SetErrorCode(73, LED_ON);                        /*all is OK, but show ID first, LED is ON as on a real 1541*/
+
+     for(lp=0; lp<MAX_NUMBER_OF_DOS_BUFFERS; lp++)    /*clear the channels*/
+    {
+        DOS_channel[lp].channel_in_use = FALSE;
+        DOS_channel[lp].filename[0] = 0;
+        DOS_channel[lp].filetype = 0;
+        DOS_channel[lp].RW = 0;    
+        DOS_channel[lp].track = 0;    
+        DOS_channel[lp].sector = 0;
+        DOS_channel[lp].buffer_pointer = 0;
+        DOS_channel[lp].used_buffer = 255;
+        DOS_channel[lp].status = NO_FILE;
+    }
+
+    for(lp=0; lp<5; lp++)                            /*clear the buffers*/
+    {
+        DOS_buffer[lp].buffer_in_use = FALSE;
+        for(lp2=0; lp2<256; lp2++)                    
+        {
+            DOS_buffer[lp].buffer[lp2] = 0;
+        }
+    }
+    DOS_buffer[4].buffer_in_use = TRUE;                /*this buffer location (or channel) is used for holding the disks BAM, therefore it is not free to be used by the user*/
+
+    DelayBigMs(2000);                                /*a small delay to keep the splash-screen visible and to ensure that the connected computer has powered up correctly, this is mainly required for the VIC20. Although the DTV version does not have an LCD (mostly) waiting 2 seconds after powerup is good practice anyway, as the IEC-bus may not be stable yet (a real drive has the same delay)*/
+    IEC_state = IDLE;
+    file_type = NONE;                                /*after reset or card insertion there is no D64 file selected, so all actions regarding current refer to the card*/
+    DiskState = NO_CARD;                            /*no card detected yet, so no D64 is selected*/
+    file_type = NONE;                                /*and because the user has selected nothing yet we are in the root, the selected file_type = NONE, as there is no image file selected and we are operating in harddiskmode*/
+    enable_ATN_interrupt();                            /*enabling the interrupt makes the system ready for use on the IEC-bus*/
+    while(1)
+    {        
+        IEC_direction_statemachine();
+    }
+}
+
+/*****************************************************************************************************************/
+/*****************************************************************************************************************/
+#define CARD_DETECT 0   // this should be a hardware pin
+
+void IEC_direction_statemachine(void)
+{
+    DelayBigUs(1000);                                    /*'frame to release of ATN'-time is at least 20uS, so we wait a bit longer before we check the status of the ATN-line... otherwise we may be interpret it incorrectly*/
+//    DelayBigUs(200);                                    /*'frame to release of ATN'-time is at least 20uS, so we wait a bit longer before we check the status of the ATN-line... otherwise we may be interpret it incorrectly*/
+    device_command = CheckForCommand(&command, TRUE);
+    while (device_command == FALSE)                        /*no commands are received so we have time for others things...*/
+    {
+ 
+        if(CARD_DETECT == 1)                            /*check if the card is present*/
+            DiskState = NO_CARD;                        /*no card detected, so no D64 is selected*/
+
+        if(DiskState == NO_CARD)
+        {
+            DelayBigMs(1000);
+            SetErrorCode(73, LED_OFF);                    /*all is OK, but show ID first, LED is OFF as on a real 1541*/
+         //   Lcd_clr();                                    /*clear screen to prepare for more serious info.*/                        
+            NoCardMenu();                                /*check if a setting button has been pressed and handle accordingly*/
+            if (CardStatus())                            /*this routine will only pass until a valid card is present*/
+            {
+                CountFiles();                            /*count all files in the current directory (which is root)*/
+                SetErrorCode(73, LED_OFF);                /*all is OK (but show ID first) set LED to color cycle to indicate that this is the first time we enter the root after card insertion or reset. Meaning that the selected file is 0 (the card itself)*/
+                file_type = NONE;                    /*after reset or card insertion there is no D64 file selected, so all actions regarding current refer to the card*/
+        //        Lcd_clr();
+                print_D64_name(PLAIN);
+                print_D64_TSB(0, 0, 0,0);                /*print Track, Sector, Block*/
+            }
+        }
+ //       else
+ //       {
+ //           SelectD64Image();                            /*check for user interaction via buttons*/
+ //       }
+        device_command = CheckForCommand(&command, TRUE);
+    }
+
+    if(CARD_DETECT == 1)                                /*check again if the card is present, some @#$#@$#@% might have removed it*/
+        DiskState = NO_CARD;                            /*no card detected, so no D64 is selected*/
+
+    
+    switch (device_command)
+    {
+        case OPEN:    /*here we decode the command string and we check if we are capable of executing the requested action*/
+        {
+            DOS_channel[channel].channel_in_use = TRUE;        /*claim this channel*/
+            WaitForString(command_string, TRUE);            /*wait for an operator string that ends with an EOI*/
+            break;
+        }
+    
+        case DATA:
+        {
+//            if (DOS_channel[channel].channel_in_use == TRUE)    /*check if this channel has been opened, if not ignore*/
+//            {
+                DataHandler();
+//            }
+//            else
+//            {
+//                OutputToRS232();                                        /*set standard output to RS232*/
+//                printf("\r\nChannel not open! Ignore DATA command");    /*!!! DEBUG ONLY !!!*/
+//                OutputToLCD();                                            /*set standard output to LCD*/
+//            }
+            break;
+        }
+
+        case CLOSE:
+        {
+//            if (channel == 15)                                    /*when the error/command channel is closed, then all files stored in the DOS buffer are closed also*/
+//            {
+/*to do: close all open files properly*/
+//            }
+//            else
+//            {
+//            }
+
+            if (DOS_channel[channel].used_buffer != 255)    /*check if there is a buffer connected to this channel*/
+            {
+                DOS_buffer[DOS_channel[channel].used_buffer].buffer_in_use = FALSE;    /*free the buffer that was connected to this channel. now this buffer is free to use for newly opened channels that might require a buffer*/
+            }
+
+            /*set the channel information back to default, although i doubt that the original 1541 does this...*/
+            DOS_channel[channel].channel_in_use = FALSE;
+            DOS_channel[channel].filename[0] = 0;
+            DOS_channel[channel].filetype = 0;
+            DOS_channel[channel].RW = 0;    
+            DOS_channel[channel].track = 0;    
+            DOS_channel[channel].sector = 0;
+            DOS_channel[channel].buffer_pointer = 0;
+            DOS_channel[channel].used_buffer = 255;
+            DOS_channel[channel].status = NO_FILE;
+
+            OutputToRS232();                        /*set standard output to RS232*/
+            printf("\r\nClose");                    /*!!! DEBUG ONLY !!!*/
+            OutputToLCD();                            /*set standard output to LCD*/
+            break;
+        }    
+
+        case UNLISTEN:
+        {
+            if (IEC_state != IDLE)                    /*make sure that this command is not the last command of a different device, if it is our device we are not IDLE anymore since the this device would have it's status set to a different thing the IDLE*/
+            {
+                if (DOS_channel[channel].channel_in_use == TRUE)    /*check if the previous command on this channel was open*/
+                {
+                    OpenHandler();
+                }
+    
+                //turn LED OFF
+//    OutputToRS232();                /*set standard output to RS232*/
+//    printf("\r\nUnlisten\r\n");            /*!!! DEBUG ONLY !!!*/
+//    OutputToLCD();                    /*set standard output to LCD*/
+                IEC_state = IDLE;
+            }
+            break;
+        }
+    
+        case UNTALK:
+        {
+            if (IEC_state != IDLE)                    /*make sure that this command is not the last command of a different device, if it is our device we are not IDLE anymore since the this device would have it's status set to a different thing the IDLE*/
+            {
+                //turn LED OFF
+                IEC_state = IDLE;
+//    OutputToRS232();                    /*set standard output to RS232*/
+//    printf("\r\nUntalk\r\n");                /*!!! DEBUG ONLY !!!*/
+//    OutputToLCD();                        /*set standard output to LCD*/
+
+            }
+            break;
+        }
+
+        default:
+        {
+            if (device_command == (LISTEN | devicenumber))
+            {
+                //turn LED ON
+                IEC_state = ACTIVE_LISTEN;
+//    OutputToRS232();                /*set standard output to RS232*/
+//    printf("\r\nListen");            /*!!! DEBUG ONLY !!!*/
+//    OutputToLCD();                    /*set standard output to LCD*/
+                break;
+            }
+    
+            if (device_command == (TALK | devicenumber))
+            {
+                //turn LED ON
+                IEC_state =    ACTIVE_TALK;
+//    OutputToRS232();                /*set standard output to RS232*/
+//    printf("\r\nTalk");                /*!!! DEBUG ONLY !!!*/
+//    OutputToLCD();                    /*set standard output to LCD*/
+                break;
+            }
+
+            /*--------------------------------------------------------------------------------------*/
+            /* current communication on the bus is incorrect or meant for another device on the bus */
+            /*--------------------------------------------------------------------------------------*/
+            disable_ATN_interrupt();    /*By disabling the ATN interrupt we do not interfer with the data that is meant for another device on the bus*/
+            FreeIEC();                    /*get of the bus...*/
+            enable_ATN_interrupt();        /*all is back to normal, enable interrupts on ATN line*/
+            IEC_state = IDLE;
+            break;
+        }
+    }
+
+    myled3=0;
+}
+
+
+void OpenHandler(void)
+{
+//    OutputToRS232();                        /*set standard output to RS232*/
+//    printf("\r\nOPENHANDLER: ");                /*!!! DEBUG ONLY !!!*/
+//    printf("command_string:%s",command_string);    /*!!! DEBUG ONLY !!!*/
+//    printf("\r\nchannel:%d",channel);        /*!!! DEBUG ONLY !!!*/
+//    OutputToLCD();                            /*set standard output to LCD*/
+
+    switch(channel)
+    {
+        case 0:                /*this channel is used for reading of files*/
+        {
+            if(DiskState == NO_CARD)
+            {
+                DOS_channel[channel].next_action = ABORT_SENDING;
+                break;
+            }
+
+            /*------------------*/
+            /* '$' = DIRECTORY  */
+            /*------------------*/
+            if ((strlen((char *)command_string) == 5) && (strncmp((char *)command_string,"$CARD", 5) == 0 ))        /*check the COMPLETE string*/
+            {    /*ROOT directory of the card*/
+                file_type = NONE;                                        /*all later actions refer to the CARD and not a D64 file*/
+                DiskState = CARD_ACTIVE;                                    /*this command overrules the buttons*/
+                DOS_channel[channel].next_action = CARD_DIRECTORY;            /*show the directory of the MMC/SD-card*/                    
+                print_D64_name(PLAIN);
+                break;
+            }
+            
+            if (((strlen((char *)command_string) == 1) && (strncmp((char *)command_string,"$",  1) == 0 )) || ((strlen((char *)command_string) == 2) && (strncmp((char *)command_string,"$0",  2) == 0 )))        /*check the COMPLETE string*/
+            {    /*current directory, which may be D64 or ROOT depending on the previous selection*/
+                if ((file_type == NONE) || (file_type == SUBDIRECTORY))        /*check for the currently selected file, if 0 refer to the card and not a D64 file*/
+                    DOS_channel[channel].next_action = CARD_DIRECTORY;        /*show the directory of the MMC/SD-card*/                    
+                else
+                    DOS_channel[channel].next_action = DIRECTORY;            /*show the directory of the currently selected D64 file*/
+                break;
+            }
+
+            if (strncmp("$", (char *)command_string, 1) == 0 )                        /*check the 1st char of the string)*/
+            {    
+                file_status = SeekFileOnCard(&command_string[1], &file);    /*check if file is present or not*/
+                if (file_status == FALSE)
+                {
+                    SetErrorCode(62,LED_ERROR);                                /*file not found*/
+                    DOS_channel[channel].next_action = ABORT_SENDING;        /*the requested directory does not exist*/
+                }
+                else
+                {
+                    DiskState = CARD_ACTIVE;                                /*this command overrules the buttons*/
+                    file_type = FileFilter();                                /*check the type of file to determine the mode of operation*/
+                    if(file_type == SUBDIRECTORY)                            /*check if the user wants to enter a subdirectory*/
+                    {
+                        OpenSubDirectory(&file);                            /*the user request to enter a subdirectory, so we call the routine that setts all registers in the correct way in order to use subdirectories properly*/
+                        file_number = 0;                                    /*the file_number counter needs to be reset*/
+                        file_type = NONE;                                    /*and because the user has selected a (sub)directory, the selected file_type = NONE, as there is no image file selected and we are operating in harddiskmode*/
+                        CountFiles();                                        /*count all files in the opened directory*/
+                        DOS_channel[channel].next_action = CARD_DIRECTORY;    /*show the (sub)directory of the MMC/SD-card*/                    
+                        print_D64_name(PLAIN);                                /*update the display*/
+                    }
+                    else
+                    {
+                        file_number = file_status;
+                        DOS_channel[channel].next_action = DIRECTORY;        /*show the directory of the requested D64 file (but only if the actions below do not fail offcourse)*/
+                        print_D64_name(PLAIN);                                /*update the display*/
+                        FileSectorScan(&file);                                /*update the sector location table cache*/
+                        D64ReadBAM();                                        /*update the BAM*/
+                    }
+                }
+                break;                                                        /*leave the case*/
+            }
+        
+            /*----------------------*/
+            /* LOAD filename        */
+            /*----------------------*/    
+            if (file_type == NONE)                                        /*check for the currently selected file, if 0 refer to the card and not a D64 file*/
+            {
+                file_status = SeekFileOnCard(command_string, &file);    /*check if file is present on the card*/
+                DOS_channel[channel].next_action = RD_FILE_FROM_ROOT;
+                break;
+            }
+            else
+            {
+                file_status = D64SeekFile(command_string, &track, &sector, &blocksize, &dirtrack, &dirsector, &direntry);    /*check if file is present within a D64 file*/
+                DOS_channel[channel].next_action = RD_FILE;
+                break;
+            }
+        }
+        
+        case 1:                /*this channel is used for writing of files*/
+        {
+            if(DiskState == NO_CARD)
+            {
+                DOS_channel[channel].next_action = ABORT_RECEIVING;
+                break;
+            }
+
+            /*------------------------------------------------------------*/
+            /* '@' = REPLACE                                              */
+            /* syntax: SAVE"@0:<filename>",x,1                            */
+            /* syntax: SAVE"@S:<filename>",8,1 (special for game:commando, int karate, donkey kong)*/
+            /*------------------------------------------------------------*/
+            if ((strncmp("@:", (char *)command_string, 2) == 0 ) || (strncmp("@0:",(char *) command_string, 3) == 0 ) || (strncmp("@S:", (char *)command_string, 3) == 0 ))            /*check the beginning of the string)*/
+            {
+                SplitStringOn_Sign(':', command_string, filename_string);
+                file_status = D64SeekFile(filename_string, &track, &sector, &blocksize, &dirtrack, &dirsector, &direntry);    /*check if file is present or not*/
+                DOS_channel[channel].next_action = REPLACE_FILE;                            /*replace a file within the currently selected D64 file*/
+                break;
+            }
+        
+            /*---------------*/
+            /* SAVE filename */
+            /*---------------*/    
+            if (file_type == NONE)        /*check for the currently selected file, if 0 refer to the card and not a D64 file*/
+            {
+                file_status = SeekFileOnCard(command_string, &file);    /*check if file is present or not*/
+                DOS_channel[channel].next_action = WR_FILE_TO_ROOT;
+                break;
+            }
+            else
+            {
+                file_status = D64SeekFile(command_string, &track, &sector, &blocksize, &dirtrack, &dirsector, &direntry);    /*check if file is present or not*/
+                DOS_channel[channel].next_action = WR_FILE;
+                break;
+            }
+        }
+
+
+        /*the channels 2-14 are used for the actual file handling that do not use the BASIC LOAD or SAVE commands*/
+        case 2:;
+        case 3:;
+        case 4:;
+        case 5:;
+        case 6:;
+        case 7:;
+        case 8:;
+        case 9:;
+        case 10:;
+        case 11:;
+        case 12:;
+        case 13:;
+        case 14:
+        {
+            if (command_string[0] == '#')                                        /*if the user/computer specifies a buffer then handle accordingly...*/
+            {        
+                if (DOS_channel[channel].used_buffer == 255)                    /*check if this channel allready has a buffer connected*/
+                {
+                    if (ValueFromString(&command_string[0], &value_1))            /*check if the user has specified it's own buffer preference*/
+                    {
+                        if (DOS_buffer[value_1].buffer_in_use == FALSE)            /*check if this buffer is still available*/
+                        {
+                            DOS_buffer[value_1].buffer_in_use = TRUE;            /*this buffer is still free, so we can claim this buffer*/
+                            DOS_channel[channel].used_buffer = value_1;            /*connect the free buffer to this channel*/
+                        }
+                        else
+                        {
+                            SetErrorCode(70, LED_ERROR);                        /*the requested buffer is allready in use, close the current situtation properly before we let the new situation claim this buffer*/
+                        }
+                    }
+                    else
+                    {
+                        nextfreebuffer = SearchFreeBuffer();                    /*since the user does not care which buffer it uses, so the 1541-III may decide which buffer is available*/
+                        if (nextfreebuffer == 255)
+                        {
+                            SetErrorCode(70, LED_ERROR);                        /*No channels available or in other words: no more free buffers */
+                        }
+                        else
+                        {
+                            DOS_buffer[nextfreebuffer].buffer_in_use = TRUE;    /*claim this buffer*/
+                            DOS_channel[channel].used_buffer = nextfreebuffer;    /*connect the free buffer to this channel*/
+                        }
+                    }
+                }
+            }
+            else
+            {
+                ExtractFilenameFromString(command_string, filename_string);    /*extract the filename from the commandstring given by the user/computer*/
+                SplitStringOn_Sign(',', command_string, filetype_string);
+                SplitStringOn_Sign(',', filetype_string, RW_string);                
+                strcpy((char *)&DOS_channel[channel].filename[0], (char *)filename_string);    /*copy the filename into the DOS buffer*/
+
+                /*check for filetype*/
+                if ((strncmp("A", (char *)filetype_string, 1) == 0 ) || (strncmp("APPEND",(char *) filetype_string, 6) == 0 ))
+                {
+                    DOS_channel[channel].filetype = SEQUENTIAL;
+//to do: zoek hier naar het einde van de sequentiele file en zet de bufferpointer track en sector waardes in de DOS buffer op de correcte waardes
+                }
+                else
+                {
+                    /*check for the filetype SEQ, REL, PRG, USR, LENGTH (checking for only the first letter is sufficient to check for all variations of the word sequential, program, etc)*/
+                    if (strncmp("S", (char *)filetype_string, 1))
+                    {
+                        DOS_channel[channel].filetype = SEQUENTIAL;
+                    }
+                    if (strncmp("R", (char *)filetype_string, 1))
+                    {
+                        DOS_channel[channel].filetype = RELATIVE;
+                    }
+                    if (strncmp("P", (char *)filetype_string, 1))
+                    {
+                        DOS_channel[channel].filetype = PROGRAM;
+                    }
+                    if (strncmp("U", (char *)filetype_string, 1) == 0 )
+                    {
+                        DOS_channel[channel].filetype = USER;
+                    }
+//                    if (strncmp("L", filetype_string, 1))
+//                    {
+//                        DOS_channel[channel].filetype = USER;
+//                    }
+    
+    
+                    /*check if file is to be used as a Read, Write or Modify (checking for only the first letter is sufficient to check for all variations of the word)*/
+                    if ((RW_string[0]==0) || (strncmp("R", (char *)RW_string, 1) == 0 ))    /*when not defined or defined as R, then the file is to be used for READ functions*/
+                    {
+                        DOS_channel[channel].RW = RD_FILE;
+                        file_status = D64SeekFile(filename_string, &track, &sector, &blocksize, &dirtrack, &dirsector, &direntry);    /*check if file is present or not*/
+                        if (file_status == FILE_PRESENT)
+                        {
+                            DOS_channel[channel].status = FILE_OPEN;    /*the file could be found*/
+                            DOS_channel[channel].track = track;            /*save, the location of the first byte regarding this file on the "disk", to the appropriate registers*/
+                            DOS_channel[channel].sector = sector;
+                            DOS_channel[channel].buffer_pointer = 0;
+                        }
+                        else
+                        {
+                            DOS_channel[channel].status = NO_FILE;        /*the file could not be found*/
+                            SetErrorCode(62,LED_ERROR);                    /*file not found*/
+                        }
+                    }
+
+                    if ((strncmp("W", (char *)RW_string, 1) == 0 ) || (strncmp("WRITE",(char *) RW_string, 5) == 0 ))
+                    {
+                        DOS_channel[channel].RW = WR_FILE;
+                        file_status = D64SeekFile(filename_string, &track, &sector, &blocksize, &dirtrack, &dirsector, &direntry);    /*check if file is present or not*/
+                        if (file_status == FILE_PRESENT)
+                        {
+                            DOS_channel[channel].status = NO_FILE;        /*the file could not be found*/
+                            SetErrorCode(63,LED_ERROR);                    /*file exists*/
+                        }
+                        else
+                        {
+                            DOS_channel[channel].status = FILE_OPEN;    /*the file could be found*/
+//to do: maak in de directory structuur een nieuwe file aan maar sluit deze (uiteraard niet af), deze file word ook wel een 'splat' file genoemd
+
+                            DOS_channel[channel].track = track;            /*save, the location of the first byte regarding this file on the "disk", to the appropriate registers*/
+                            DOS_channel[channel].sector = sector;
+                            DOS_channel[channel].buffer_pointer = 0;
+                        }
+                    }
+                    if ((strncmp("M", (char *)RW_string, 1) == 0 ) || (strncmp("MODIFY", (char *)RW_string, 6) == 0 ))
+                    {
+                        DOS_channel[channel].RW = MODIFY_FILE;
+//to do: uitzoeken wat modify precies inhoud...
+                    }
+
+                }
+            }
+
+            OutputToRS232();                        /*set standard output to RS232*/
+            printf("\r\nOpen, channel %d", channel);    /*!!! DEBUG ONLY !!!*/
+            printf("\r\n  channel_in_use:%03d",DOS_channel[channel].channel_in_use);
+            printf("\r\n  next_action   :%03d",DOS_channel[channel].next_action);
+            printf("\r\n  filename[0]   :%s",DOS_channel[channel].filename);
+            printf("\r\n  filetype      :%03d",DOS_channel[channel].filetype);
+            printf("\r\n  RW            :%03d",DOS_channel[channel].RW);
+            printf("\r\n  track         :%03d",DOS_channel[channel].track);
+            printf("\r\n  sector        :%03d",DOS_channel[channel].sector);
+            printf("\r\n  buffer_pointer:%03d",DOS_channel[channel].buffer_pointer);
+            printf("\r\n  used_buffer   :%03d",DOS_channel[channel].used_buffer);
+            printf("\r\n  status        :%03d",DOS_channel[channel].status);
+            printf("\r\n");                            /*!!! DEBUG ONLY !!!*/
+            OutputToLCD();                            /*set standard output to LCD*/
+            break;
+        }
+
+        case 15:
+        {
+            /*------------------------------------------------------*/
+            /* Set LCD's contrast                                   */
+            /* Syntax: "LCDCONTRAST=<value>"                        */
+            /* Example: OPEN15,device,15,"LCDCONTRAST=ddd"<RETURN>  */
+            /*          CLOSE 15<RETURN>                            */
+            /*------------------------------------------------------*/
+            if (strncmp("LCDCONTRAST=",(char *)command_string,12) == 0 )        /*check the beginning of the string)*/
+            {
+                SplitStringOn_Sign('=', command_string, value_string);
+                ValueFromString(value_string, &value_1);
+                if (value_1>0 && value_1<255)
+                {
+                    setting_contrast = value_1;                    /*copy new value to the correct register*/
+                    // SetContrast();                                /*apply new setting*/
+                    // SaveSettingsToEEPROM();                        /*save value to EEPROM*/
+                    print_device_status("  CONTRAST... ");
+                }
+                else
+                {    /*incorrect value*/
+                    FreeIEC();                                    /*BUT... since there's no use in receiving data we cannot process, free the bus and the computer will detect this as an valid error situation*/
+                }
+                DOS_channel[channel].channel_in_use = FALSE;    /*no further actions required*/    
+            }
+        
+            /*----------------------------------------------------------------*/
+            /* 'N' = NEW - Format a floppy disk                               */
+            /* Syntax: "NEW:<diskname>,<id>"                                  */
+            /* Example: OPEN 15,8,15,"N:diskname,01"<RETURN>                  */
+            /*          CLOSE 15<RETURN>                                      */
+            /* <diskname> can be up to 16 characters                          */
+            /* <id> can either be omitted or must be exactly 2 characters long*/
+            /*----------------------------------------------------------------*/
+            if ((strncmp("N:",(char *)command_string,2) == 0 ) || (strncmp("N0:",(char *)command_string,3) == 0 ) || (strncmp("NEW:",(char *)command_string,4) == 0 ) || (strncmp("NEW0:",(char *)command_string,5) == 0 ))                        /*check the beginning of the string)*/
+            {
+                if (file_type == D64_35T_MODE)    //future or TODO: D64_35T_ER_MODE, D64_40T_MODE, D64_40T_ER_MODE
+                {
+                    print_device_status(" FORMATTING.. ");
+                    SplitStringOn_Sign(':', command_string, filename_string);
+                    SplitStringOn_Sign(',', filename_string, value_string);
+                    FormatD64File(filename_string, value_string);
+                }
+                else
+                {    /*creating a disk in the root directory is not supported*/
+                    FreeIEC();                                    /*BUT... since there's no use in receiving data we cannot process, free the bus and the computer will detect this as an valid error situation*/
+                }
+                DOS_channel[channel].channel_in_use = FALSE;    /*no further actions required*/    
+            }
+        
+            /*----------------------------------------------------------------------------------------*/
+            /* 'S' = SCRATCH (also referred to as 'delete')                                           */
+            /* Syntax: "SCRATCH:<file>"                                                               */
+            /* Example: OPEN 15,8,15,"S:filename"<RETURN>                                             */
+            /*          CLOSE 15<RETURN>   (do not forget otherwise remaining commands may not work)  */
+            /* You can use the wild cards '?' and '*' to delete several files at once.                */
+            /*----------------------------------------------------------------------------------------*/
+            if ((strncmp("S:",(char *)command_string,2) == 0 ) || (strncmp("S0:",(char *)command_string,3) == 0 ) || (strncmp("SCRATCH:",(char *)command_string,8) == 0 ) || (strncmp("SCRATCH0:",(char *)command_string,9) == 0 ))    /*check the beginning of the string)*/
+            {
+                SplitStringOn_Sign(':', command_string, filename_string);
+                file_status = D64SeekFile(filename_string, &track, &sector, &blocksize, &dirtrack, &dirsector, &direntry);    /*check if file is present or not*/
+                if (file_status == FILE_PRESENT)
+                {
+                    files_scratched = 0;                    /*the error message abuses this variable for the number of files scratched, so... we must do this also to simulate the 1541 as good as possible*/
+                    SetErrorCode(0,LED_ON);                    /*unless we fail we will exit with no error*/
+                      while(file_status == FILE_PRESENT)        /*this function uses wildcards, so the same function needs to be repeated, keep checking untill false*/
+                    {
+                        print_device_status(" SCRATCHING.. ");
+                        D64ScratchDirEntry(dirtrack, dirsector, direntry);
+                        files_scratched++;
+                        file_status = D64SeekFile(filename_string, &track, &sector, &blocksize, &dirtrack, &dirsector, &direntry);    /*check if file is present or not*/
+                    }
+                    SetErrorCode(1,LED_OFF);
+                }
+                else
+                {
+                    SetErrorCode(62,LED_ERROR);                    /*file not found*/
+                    FreeIEC();                                    /*BUT... since there's no use in receiving data we cannot process, free the bus and the computer will detect this as an valid error situation*/
+                }
+                DOS_channel[channel].channel_in_use = FALSE;    /*no further actions required*/    
+            }
+        
+            /*--------------------------------------------------*/
+            /* 'R' = RENAME - Rename a file                     */
+            /* Syntax: "RENAME:<newname>=<oldname>"             */
+            /* Example:    OPEN 15,8,15,"R:newfilename=oldfilename"*/
+            /*          CLOSE 15<RETURN>                        */
+            /*--------------------------------------------------*/
+            if ((strncmp("R:",(char *)command_string,2) == 0 ) || (strncmp("R0:",(char *)command_string,3) == 0 ) || (strncmp("RENAME:",(char *)command_string,7) == 0 ) || (strncmp("RENAME0:",(char *)command_string,8) == 0 ))    /*check the beginning of the string)*/
+            {
+                SplitStringOn_Sign(':', command_string, filename_string);
+                SplitStringOn_Sign('=', filename_string, oldfilename_string);
+                file_status = D64SeekFile(oldfilename_string, &track, &sector, &blocksize, &dirtrack, &dirsector, &direntry);    /*check if file is present or not*/
+                if (file_status == FILE_PRESENT)                /*although the '=0' has to be given in the command, we do not check for it*/
+                {
+                    print_device_status("  RENAMING..  ");
+                    SetErrorCode(0,LED_ON);                        /*unless we fail we will exit with no error*/
+                    D64RenameDirEntry(filename_string, dirtrack, dirsector, direntry);
+                    SetErrorCode(0,LED_OFF);                    /*we exit without error*/
+                }
+                else
+                {
+                    SetErrorCode(62,LED_ERROR);                    /*file not found*/
+                    FreeIEC();                                    /*BUT... since there's no use in receiving data we cannot process, free the bus and the computer will detect this as an valid error situation*/
+                }
+                DOS_channel[channel].channel_in_use = FALSE;    /*no further actions required*/    
+            }
+        
+        
+            /*----------------------------------------*/
+            /* INITIALIZE - re-read the BAM from disk */ 
+            /* Abbreviation: I                        */
+            /* Syntax: "INITIALIZE"                   */
+            /*----------------------------------------*/    
+            /*Currently, this command is not supported            */
+        
+        
+            /*----------------------------------------------------*/
+            /* VALIDATE - Check and Fix Disk Consistency           */
+            /* Abbreviation: V                                       */
+            /* Syntax: "VALIDATE"                                  */
+            /*----------------------------------------------------*/
+            /*Currently, this command is not supported            */
+            /*Validate will fix inconsistencies that can be caused by files that where opened but never closed. Beware: Validate also erases all random files! */
+        
+        
+            /*-------------------------------------------------------*/
+            /* 'C' = COPY - Create a copy of a file on the same disk */
+            /* Syntax: "COPY:<destfile>=<sourcefile>" or "COPY:<destfile>=<sourcefile1>, <sourcefile2>, ..."*/
+            /* If several source files are listed, than the destination file will contain the concatenated contents of all source files. */
+            /*-------------------------------------------------------*/
+            if ((strncmp("C:",(char *)command_string,2) == 0 ) || (strncmp("C0:",(char *)command_string,3) == 0 ) || (strncmp("COPY:",(char *)command_string,5) == 0 ) || (strncmp("COPY0:",(char *)command_string,6) == 0 ))            /*check the beginning of the string)*/
+            {
+                SplitStringOn_Sign(':', command_string, filename_string);
+                SplitStringOn_Sign('=', filename_string, oldfilename_string);
+                file_status = D64SeekFile(oldfilename_string, &track, &sector, &blocksize, &dirtrack, &dirsector, &direntry);    /*check if file is present or not*/
+                if (file_status == FILE_PRESENT)
+                {
+                    print_device_status("  COPYING...  ");
+                    CopyD64File(track, sector, blocksize);
+                }
+                else
+                {
+                    SetErrorCode(62,LED_ERROR);                    /*file not found*/
+                    FreeIEC();                                    /*BUT... since there's no use in receiving data we cannot process, free the bus and the computer will detect this as an valid error situation*/
+                }
+                DOS_channel[channel].channel_in_use = FALSE;    /*no further actions required*/    
+            }
+        
+            /*-------------------------------------------------------*/
+            /* 'M-W' = memory write command                           */
+            /* Syntax: OPEN 15,8,15,"M-W"CHR$(lowbyteaddr)CHR$(highbyteaddr)CHR$(numberofmemorylocations)CHR$(data)CHR$(data)CHR$(data):CLOSE 1<RETURN>    */
+            /*-------------------------------------------------------*/
+            if ((strncmp("M-W",(char *)command_string,3) == 0 ))    // || (strncmp("M-W:", command_string, 4) == 0 ))        /*check the COMPLETE string*/
+            {
+                if((command_string[3] == 119) && (command_string[4] == 0) && (command_string[5] == 2))
+                {
+                    if((command_string[6] - 32) == (command_string[7] - 64))    /*check for new device address*/
+                    {    
+                        devicenumber = command_string[7] - 64;            /*the new IEC device address of this device*/
+                        print_device_status("  NEW DEVICE# ");
+                        SetErrorCode(0,LED_ON);                            /*unless we fail we will exit with no error*/
+                        print_D64_TSB(0,0,0,0);                            /*update display with the new device address*/
+                        SetErrorCode(0,LED_OFF);                        /*we exit without error*/
+                        DOS_channel[channel].channel_in_use = FALSE;    /*no further actions required*/    
+                    }
+                }
+            }
+        
+            /*--------------------------------------------------------------------------------------------------------*/
+            /* 'B-P' = buffer pointer command (i.o.w. Set the buffer pointer used by CHANNEL ??? to point to BYTE ??? */
+            /* Syntax: OPEN 15,8,15,"B-P:";channel;byte:CLOSE 15<RETURN>                                              */
+            /* Example: OPEN 15,8,15,"B-P:";5;2:CLOSE 15<RETURN>                                                      */
+            /* Example: OPEN 15,8,15,"B-P";5;2:CLOSE 15<RETURN>                                                          */
+            /* Example: OPEN 15,8,15,"B-P 5 2":CLOSE 15<RETURN>                                                          */
+            /*--------------------------------------------------------------------------------------------------------*/
+            if ((strncmp("B-P",(char *)command_string,3) == 0 ))        /*check the string*/
+            {
+                string_pntr = 0;
+                string_pntr_2=ValueFromString(&command_string[string_pntr],&value_1);            /*search for the 1st number: channel*/
+                if (string_pntr_2!=FALSE)
+                {
+                    string_pntr = string_pntr + string_pntr_2;
+                    string_pntr_2=ValueFromString(&command_string[string_pntr],&value_2);        /*search for the 2nd number: channel*/            
+                    if (string_pntr_2 != FALSE)
+                    {
+                        DOS_channel[value_1].buffer_pointer = value_2;    /*the BufferPointer of this channel (used when reading/writing the connected buffer), needs to be set to value_2*/                
+                        OutputToRS232();                        /*set standard output to RS232*/
+                        printf("\r\nB-P command, channel:%02d, BP:%03d",value_1,DOS_channel[DOS_channel[value_1].used_buffer].buffer_pointer);
+                        OutputToLCD();                            /*set standard output to LCD*/
+                    }
+                }
+            }
+        
+        
+            /*-------------------------------------------------------------------------*/
+            /* 'B-R' = USER-command 1 (254 bytes, byte 0-1 are skipped)                */
+            /* Syntax: OPEN 15,8,15,"B-R"channel;drive;track;sector":CLOSE 15<RETURN>  */
+            /*-------------------------------------------------------------------------*/
+            if ((strncmp("B-R",(char *)command_string,3) == 0 ))        /*check the string*/
+            {        
+                string_pntr = 2;        /*whatever the command, skip the first 2 characters in searching for the first number. Otherwise the 1 from U1 might be recognised as a value, which it is not*/
+                string_pntr_2=ValueFromString(&command_string[string_pntr],&value_1);                /*search for the 1st number: channel*/
+                if (string_pntr_2!=FALSE)
+                {
+                    if (DOS_channel[value_1].used_buffer!=255)    /*check if the specified channel has been connected to a buffer, if not ignore the rest of the command*/
+                    {
+                        string_pntr = string_pntr + string_pntr_2;
+                        string_pntr_2=ValueFromString(&command_string[string_pntr],&value_2);            /*search for the 2nd number: channel*/            
+                        if (string_pntr_2 != FALSE)
+                        {
+                            string_pntr = string_pntr + string_pntr_2;
+                            string_pntr_2=ValueFromString(&command_string[string_pntr],&value_3);        /*search for the 2nd number: channel*/            
+                            if (string_pntr_2 != FALSE)
+                            {
+                                string_pntr = string_pntr + string_pntr_2;
+                                string_pntr_2=ValueFromString(&command_string[string_pntr],&value_4);    /*search for the 2nd number: channel*/            
+                                if (string_pntr_2 != FALSE)
+                                {
+                                    DOS_channel[value_1].track = value_3;                                /*we have all the info we need, so save this info the the appropriate registers and we're done*/
+                                    DOS_channel[value_1].sector = value_4;                                /*save track and sector info*/
+                                    D64BlockRead_new(DOS_channel[value_1].used_buffer,value_3,value_4);    /*read the desired block of the D64 image and store it into the desired buffer*/
+    
+                                    OutputToRS232();                        /*set standard output to RS232*/
+                                    printf("\r\nB-R command, t:%03d, s:%03d",DOS_channel[value_1].track,DOS_channel[value_1].sector);
+                                    OutputToLCD();                            /*set standard output to LCD*/
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        
+        
+            /*-------------------------------------------------------------------------*/
+            /* 'U1' or 'UA' = USER-command 1 (block read, 256 bytes)                   */
+            /* Syntax: OPEN 15,8,15,"U1:"channel;drive;track;sector":CLOSE 15<RETURN>  */
+            /* Example: OPEN 15,8,15,"U1:";5;0;18;1:CLOSE 15<RETURN>                   */
+            /* Example: OPEN 15,8,15,"U1";5;0;18;1:CLOSE 15<RETURN>                       */
+            /* Example: OPEN 15,8,15,"U1 5 0 18 1":CLOSE 15<RETURN>                       */
+            /*-------------------------------------------------------------------------*/
+            if (((strncmp("UA",(char *)command_string,2) == 0 )) || ((strncmp("U1",(char *)command_string,2) == 0 )))        /*check the string*/
+            {        
+                string_pntr = 2;        /*whatever the command, skip the first 2 characters in searching for the first number. Otherwise the 1 from U1 might be recognised as a value, which it is not*/
+                string_pntr_2=ValueFromString(&command_string[string_pntr],&value_1);                /*search for the 1st number: channel*/
+                if (string_pntr_2!=FALSE)
+                {
+                    if (DOS_channel[value_1].used_buffer!=255)    /*check if the specified channel has been connected to a buffer, if not ignore the rest of the command*/
+                    {
+                        string_pntr = string_pntr + string_pntr_2;
+                        string_pntr_2=ValueFromString(&command_string[string_pntr],&value_2);            /*search for the 2nd number: channel*/            
+                        if (string_pntr_2 != FALSE)
+                        {
+                            string_pntr = string_pntr + string_pntr_2;
+                            string_pntr_2=ValueFromString(&command_string[string_pntr],&value_3);        /*search for the 2nd number: channel*/            
+                            if (string_pntr_2 != FALSE)
+                            {
+                                string_pntr = string_pntr + string_pntr_2;
+                                string_pntr_2=ValueFromString(&command_string[string_pntr],&value_4);    /*search for the 2nd number: channel*/            
+                                if (string_pntr_2 != FALSE)
+                                {
+                                    DOS_channel[value_1].track = value_3;                                /*we have all the info we need, so save this info the the appropriate registers and we're done*/
+                                    DOS_channel[value_1].sector = value_4;                                /*save track and sector info*/
+                                    D64BlockRead_new(DOS_channel[value_1].used_buffer,value_3,value_4);    /*read the desired block of the D64 image and store it into the desired buffer*/
+
+                                    OutputToRS232();                        /*set standard output to RS232*/
+                                    printf("\r\nU1 command, t:%03d, s:%03d",DOS_channel[value_1].track,DOS_channel[value_1].sector);
+                                    OutputToLCD();                            /*set standard output to LCD*/
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        
+        
+            /*-------------------------------------------------------------------------*/
+            /* 'B-W' = USER-command 2 (254 bytes block write)                               */
+            /* Syntax: OPEN 15,8,15,"U2:"channel;drive;track;sector":CLOSE 15<RETURN>  */
+            /*-------------------------------------------------------------------------*/
+            if ((strncmp("B-W",(char *)command_string,3) == 0 ))
+            {
+                string_pntr = 2;        /*whatever the command, skip the first 2 characters in searching for the first number. Otherwise the 2 from U2 might be recognised as a value, which it is not*/
+                string_pntr_2=ValueFromString(&command_string[string_pntr],&value_1);                /*search for the 1st number: channel*/
+                if (string_pntr_2!=FALSE)
+                {
+                    if (DOS_channel[value_1].used_buffer!=255)    /*check if the specified channel has been connected to a buffer, if not ignore the rest of the command*/
+                    {    
+                        string_pntr = string_pntr + string_pntr_2;
+                        string_pntr_2=ValueFromString(&command_string[string_pntr],&value_2);            /*search for the 2nd number: channel*/            
+                        if (string_pntr_2 != FALSE)
+                        {
+                            string_pntr = string_pntr + string_pntr_2;
+                            string_pntr_2=ValueFromString(&command_string[string_pntr],&value_3);        /*search for the 2nd number: channel*/            
+                            if (string_pntr_2 != FALSE)
+                            {
+                                string_pntr = string_pntr + string_pntr_2;
+                                string_pntr_2=ValueFromString(&command_string[string_pntr],&value_4);    /*search for the 2nd number: channel*/            
+                                if (string_pntr_2 != FALSE)
+                                {
+                                    DOS_channel[value_1].track = value_3;                                /*we have all the info we need, so save this info the the appropriate registers and we're done*/
+                                    DOS_channel[value_1].sector = value_4;                                /*save track and sector info*/
+                                    D64BlockWrite_new(DOS_channel[value_1].used_buffer,value_3,value_4);                                        /*write the desired block of the D64 image*/
+
+                                    OutputToRS232();                        /*set standard output to RS232*/
+                                    printf("\r\nB-W command, t:%03d, s:%03d",DOS_channel[value_1].track,DOS_channel[value_1].sector);
+                                    OutputToLCD();                            /*set standard output to LCD*/
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+
+            /*-------------------------------------------------------------------------*/
+            /* 'U2' or 'UB' = USER-command 2 (256 byte block write)                    */
+            /* Syntax: OPEN 15,8,15,"U2:"channel;drive;track;sector":CLOSE 15<RETURN>  */
+            /* Example: OPEN 15,8,15,"U2:";5;0;18;1:CLOSE 15<RETURN>                   */
+            /* Example: OPEN 15,8,15,"U2";5;0;18;1:CLOSE 15<RETURN>                       */
+            /* Example: OPEN 15,8,15,"U2 5 0 18 1":CLOSE 15<RETURN>                       */
+            /*-------------------------------------------------------------------------*/
+        
+            if (((strncmp("U2",(char *)command_string,2) == 0 )) || ((strncmp("UB",(char *)command_string,2) == 0 )))        /*check the string*/
+            {
+                string_pntr = 2;        /*whatever the command, skip the first 2 characters in searching for the first number. Otherwise the 2 from U2 might be recognised as a value, which it is not*/
+                string_pntr_2=ValueFromString(&command_string[string_pntr],&value_1);                /*search for the 1st number: channel*/
+                if (string_pntr_2!=FALSE)
+                {
+                    if (DOS_channel[value_1].used_buffer!=255)    /*check if the specified channel has been connected to a buffer, if not ignore the rest of the command*/
+                    {    
+                        string_pntr = string_pntr + string_pntr_2;
+                        string_pntr_2=ValueFromString(&command_string[string_pntr],&value_2);            /*search for the 2nd number: channel*/            
+                        if (string_pntr_2 != FALSE)
+                        {
+                            string_pntr = string_pntr + string_pntr_2;
+                            string_pntr_2=ValueFromString(&command_string[string_pntr],&value_3);        /*search for the 2nd number: channel*/            
+                            if (string_pntr_2 != FALSE)
+                            {
+                                string_pntr = string_pntr + string_pntr_2;
+                                string_pntr_2=ValueFromString(&command_string[string_pntr],&value_4);    /*search for the 2nd number: channel*/            
+                                if (string_pntr_2 != FALSE)
+                                {
+                                    DOS_channel[value_1].track = value_3;                                /*we have all the info we need, so save this info the the appropriate registers and we're done*/
+                                    DOS_channel[value_1].sector = value_4;                                /*save track and sector info*/
+                                    D64BlockWrite_new(DOS_channel[value_1].used_buffer,value_3,value_4);                                        /*write the desired block of the D64 image*/
+
+                                    OutputToRS232();                        /*set standard output to RS232*/
+                                    printf("\r\nU2 command, t:%03d, s:%03d",DOS_channel[value_1].track,DOS_channel[value_1].sector);
+                                    OutputToLCD();                            /*set standard output to LCD*/
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+
+        
+            /*-------------------------------------------------------*/
+            /* 'UI-' = USER-command speed up drive by 25%             */
+            /* Syntax: OPEN 15,8,15,"UI-":CLOSE 1<RETURN>                 */
+            /*-------------------------------------------------------*/
+            if (strncmp("UI-",(char *)command_string,3) == 0 )        /*check the string*/
+            {
+                print_device_status("  VIC20-MODE  ");
+                SetErrorCode(0,LED_ON);                            /*unless we fail we will exit with no error*/
+                SetIEC_timings(TIMINGS_VIC20);                    /*set timings according the VIC-20 settings (25% faster mode)*/
+                VIC20_mode = TRUE;                                /*raise flag*/
+                // SaveSettingsToEEPROM();                            /*store new setting*/
+                SetErrorCode(0,LED_OFF);                        /*we exit without error*/
+                DOS_channel[channel].channel_in_use = FALSE;    /*no further actions required*/    
+            }
+        
+            /*-------------------------------------------------------*/
+            /* 'UI+' = USER-command restore drive speed to normal     */
+            /* Syntax: OPEN 15,8,15,"UI+":CLOSE 1<RETURN>                 */
+            /*-------------------------------------------------------*/
+            if (strncmp("UI+",(char *)command_string,3) == 0 )        /*check the string*/
+            {
+                print_device_status("   C64-MODE   ");
+                SetErrorCode(0,LED_ON);                            /*unless we fail we will exit with no error*/
+                SetIEC_timings(TIMINGS_DEFAULT);                /*set timings according the default settings (C64 compatible mode)*/
+                VIC20_mode = FALSE;                                /*raise flag*/
+                // SaveSettingsToEEPROM();                            /*store new setting*/
+                SetErrorCode(0,LED_OFF);                        /*we exit without error*/
+                DOS_channel[channel].channel_in_use = FALSE;    /*no further actions required*/    
+            }
+
+            /*------------------------------*/
+            /* In case none of the above... */
+            /*------------------------------*/
+        //to do:syntax error
+            DOS_channel[channel].channel_in_use = FALSE;    /*no further actions required*/    
+//            print_device_status("              ");                /*remove the 'action' message from the display*/
+        }
+    }
+}
+
+void DataHandler(void)
+{
+//    OutputToRS232();                        /*set standard output to RS232*/
+//    printf("\r\nDATAHANDLER");                /*!!! DEBUG ONLY !!!*/
+//    printf("\r\nData, channel %d",channel);    /*!!! DEBUG ONLY !!!*/
+//    printf("\r\ncmd_string:%s",command_string);    /*!!! DEBUG ONLY !!!*/
+//    printf("\r\nchannel:%d",channel);        /*!!! DEBUG ONLY !!!*/
+//    OutputToLCD();                            /*set standard output to LCD*/
+
+    switch(channel)
+    {                        /*-------------------------------------------*/
+        case 0:                /* this channel is used for reading of files */
+        {                    /*-------------------------------------------*/    
+            if ((DiskState == NO_CARD) || (DiskState == INVALID_POINTER))        /*escape sequence when no D64 is selected or no card is present*/
+            {
+                DOS_channel[channel].next_action = ABORT_SENDING;
+            }
+            
+            switch(DOS_channel[channel].next_action)
+            {
+                case ABORT_SENDING:            /*file not found situation*/
+                {
+                    SetErrorCode(62,LED_ERROR);                /*file not found*/
+                    IEC_turnaround();        /*we now SEND data to the bus so... make our device a talker*/
+                    FreeIEC();                /*BUT... since there's nothing to send, free the bus and the computer will detect this as an valid error situation*/
+                    break;
+                }
+
+                case CARD_DIRECTORY:
+                {
+                    print_device_status("  LOADING...  ");
+                    CardDirectory();                        /*send the MMC/SD_card Directory information*/
+                    print_device_status("             ");
+                    break;
+                }
+        
+                case DIRECTORY:
+                {
+                    print_device_status(" LOADING DIR. ");
+                    D64Directory();                        /*send ImageDirectory information of the selected drive*/                    
+                    print_device_status("              ");
+                    break;
+                }
+        
+                case RD_FILE_FROM_ROOT:
+                {
+                    if (file_status != FALSE)
+                    {
+                        print_device_status("  LOADING...  ");
+                        OutputToRS232();
+                        printf("%s",command_string);        /*print filename on first line of LCD*/
+                        OutputToLCD();
+                        LoadFileFromCard(&file);
+                        print_device_status("              ");
+                    }
+                    else
+                    {
+                        SetErrorCode(62,LED_ERROR);                /*file not found*/
+                        IEC_turnaround();        /*we now SEND data to the bus so... make our device a talker*/
+                        FreeIEC();                /*BUT... since there's nothing to send, free the bus and the computer will detect this as an valid error situation*/
+                        DOS_channel[channel].next_action = ABORT_SENDING;
+                    }
+                    break;
+                }
+        
+                case RD_FILE:
+                {
+                    if (file_status == FILE_PRESENT)
+                    {
+                        print_device_status("  LOADING...  ");
+                        OutputToRS232();                
+                        printf("%s",command_string);            /*print filename to LCD*/
+                        OutputToLCD();
+                        LoadD64File(track, sector, blocksize);     /*load the actual file from the D64-file*/
+                        print_device_status("              ");
+                    }
+                    else
+                    {
+                        SetErrorCode(62,LED_ERROR);                /*file not found*/
+                        IEC_turnaround();        /*we now SEND data to the bus so... make our device a talker*/
+                        FreeIEC();                /*BUT... since there's nothing to send, free the bus and the computer will detect this as an valid error situation*/
+                        DOS_channel[channel].next_action = ABORT_SENDING;
+                        print_device_status("              ");
+                    }
+                    break;
+                }
+            }
+            break;
+        }
+
+                            /*-------------------------------------------*/        
+        case 1:                /* this channel is used for writing of files */
+        {                    /*-------------------------------------------*/
+            if ((DiskState == NO_CARD) || (DiskState == INVALID_POINTER))        /*escape sequence when no D64 is selected or no card is present*/
+                DOS_channel[channel].next_action = ABORT_RECEIVING;
+
+            switch(DOS_channel[channel].next_action)
+            {
+                case ABORT_RECEIVING:        /*file not found situation*/
+                {
+                    SetErrorCode(28,LED_ERROR);/*write error (a message that normally would not be possible but was created for completeness in the DOS. Now we can use it...)*/
+                    FreeIEC();                /*BUT... since there's no use in receiving data we cannot process, free the bus and the computer will detect this as an valid error situation*/
+                    break;
+                }
+
+                case WR_FILE_TO_ROOT:
+                {
+                    SetErrorCode(28,LED_ERROR);/*write error (a message that normally would not be possible but was created for completeness in the DOS. Now we can use it...)*/
+                    FreeIEC();                /*BUT... since there's no use in receiving data we cannot process, free the bus and the computer will detect this as an valid error situation*/
+                    DOS_channel[channel].next_action = ABORT_RECEIVING;
+                    break;
+                }
+        
+                case WR_FILE:
+                {
+                    if (file_status == FILE_NOT_PRESENT)
+                    {
+                        print_device_status("   SAVING...  ");
+                        OutputToRS232();                
+                        printf("%s",command_string);            /*print filename on first line of LCD*/
+                        OutputToLCD();
+                        SaveD64File();                            /*save the actual file to the D64-file*/
+                        print_device_status("              ");
+                    }
+                    else
+                    {
+                        SetErrorCode(63,LED_ERROR);                /*file exists*/
+                        FreeIEC();                /*BUT... since there's no use in receiving data we cannot process, free the bus and the computer will detect this as an valid error situation*/
+                        DOS_channel[channel].next_action = ABORT_RECEIVING;
+                    }
+                    break;
+                }
+        
+                case REPLACE_FILE:
+                {
+                    if (file_status == FILE_PRESENT)
+                    {
+                        print_device_status("  REPLACING.. ");
+                        D64ScratchDirEntry(dirtrack, dirsector, direntry);    /*remove entry*/
+                        files_scratched = 1;
+                        strcpy((char *)command_string,(char *) filename_string);            /*make sure the save routine uses the correct data, the command without the @0:*/
+                        SaveD64File();                                        /*save the actual file to the D64-file*/
+                        print_device_status("              ");
+                    }
+                    break;
+                }
+            }
+            break;
+        }
+            
+        case 2:;        /*these channels are used for...*/
+        case 3:;
+        case 4:;
+        case 5:;
+        case 6:;
+        case 7:;
+        case 8:;
+        case 9:;
+        case 10:;
+        case 11:;
+        case 12:;
+        case 13:;
+        case 14:
+        {
+            if (IEC_state == ACTIVE_TALK)    /*if the drive is expected to TALK... speak now*/
+            {
+                EOI = FALSE;
+                LED_GREEN = 1;                            /*drive LED-ON*/
+                disable_ATN_interrupt();                /*since we are a talker now and the listener may interrupt us with an ATN, we must disable interrupts on ATN line, otherwise we create a lock up situation (ATN interrupt pulls data-line low)*/
+                IEC_turnaround();                        /*we now SEND data to the bus so... make our device a talker*/
+                while(IEC_ATN() == 1)                        /* the listener (computer) indicates (by making ATN=0) it requires no more data (for now)*/
+                {
+                    if (command_string[0] == '#')                        /*if the user's/computer's last command specified opening a buffer, then handle accordingly...*/
+                    {
+                        command_string[0] = 0;                            /*make sure the command string is discarded to prevent looping*/
+                        IEC_send(DOS_channel[channel].used_buffer);        /*send the buffer number of the just opened buffer*/
+                    }
+                    else
+                    {
+//                        if (DOS_channel[channel].buffer_pointer == 255)        /*when the last byte is going to been send*/
+//                        {
+//                            EOI = TRUE;                                        /*indicate that this is the last byte of the buffer*/
+//                        }
+                        IEC_send(DOS_buffer[DOS_channel[channel].used_buffer].buffer[DOS_channel[channel].buffer_pointer]);    /*get the data from the buffer connected to this channel at the bufferposition as pointed to by the buffer-pointer*/
+                        DOS_channel[channel].buffer_pointer++;                /*increment buffer pointer by one*/            
+                    }
+                    /*wait for the listener (computer) to release the data-line (ready to receive data), this may take forever... (according the IEC-bus definition)*/
+                    while (IEC_DATA() == 0);            /*data is released when new data can be handled by the listener (the computer at this stage)*/
+                                                    /*OR*/
+                                                    /*data is released when ATN goes low because NO MORE data is required*/
+                }    
+                IEC_undoturnaround();
+                enable_ATN_interrupt();                            /*all is back to normal, enable interrupts on ATN line*/
+                SetErrorCode(0,LED_OFF);                        /*error-code is 0, LED is OFF*/
+            }
+
+            if (IEC_state == ACTIVE_LISTEN)    /*if the drive is expected to listen then... we're all ear*/
+            {
+    OutputToRS232();    /*set standard output to RS232*/
+    printf("\r\ntp10 active listen");    /*!!! DEBUG ONLY !!!*/
+    OutputToLCD();        /*set standard output to LCD*/
+            }
+
+            break;
+        }
+        
+                                /*---------------------------------------*/
+        case 15:                /* this channel is used for DOS-commands */
+        {                        /*---------------------------------------*/
+            if (IEC_state == ACTIVE_TALK)
+//            if ((IEC_state == ACTIVE_TALK) && (DOS_channel[15].channel_in_use == TRUE))
+            {
+                /*-------------------------------------------------------*/
+                /* Reading the error channel is a special situation      */
+                /* Example: OPEN 15,8,15<RETURN>                         */        
+                /*          INPUT#15, A, B$, C, D<RETURN>                */
+                /*          CLOSE 15<RETURN>                             */
+                /*-------------------------------------------------------*/
+                SendErrorMessage();            /*this is handled immediately*/
+            }
+            else
+            {
+                DOS_channel[channel].channel_in_use = TRUE;        /*claim this channel*/
+                WaitForString(command_string, TRUE);            /*wait for an operator string that ends with an EOI*/
+            }
+
+            break;
+        }
+    }
+}
+
+/*****************************************************************************************************************/
+/*The following routine will check for the PCB type by testing for the capacitor value on port RA0*/
+/*During this testing procedure no buttons may be pressed*/
+void AutoDetectPcbType(void)
+{
+
+        PCB_type = v1_1;                                            /*typical timer value: 10771 - 10835*/
+}
+
+void NoCardMenu(void)
+{
+    // Lcd_XY_address(0,0);
+    putch('o');
+ //   Lcd_XY_address(0,2);
+    putch(0x16);
+ //   Lcd_XY_address(0,4);
+    putch('i');
+    while(ReadButtons())
+    {
+        if    (button_prev == TRUE)                        /*decrease contrast (lighter)*/
+        {                                                /*---------------------------*/
+            setting_contrast--;
+            if (setting_contrast < 0x81)
+            {
+                setting_contrast = 0x81;                /*lower limit*/
+   //             Lcd_XY_address(0,1);
+                printf(" Min. reached ");
+                DelayBigMs(350);
+            }
+            else
+            {
+//                SetContrast();                            /*apply new setting*/
+     //           Lcd_XY_address(0,1);
+       //         Lcd_ProgressBar((0xff-setting_contrast), 0x81);
+         //       SaveSettingsToEEPROM();                    /*save value to EEPROM*/
+                DelayBigMs(200);
+            }
+            OutputToRS232();                            /*set standard output to RS232*/
+            printf("\r\nLCD-Lighter, contrast =%02x",setting_contrast);
+            OutputToLCD();                                /*set standard output to LCD*/
+        }
+        
+        if    (button_select == TRUE)                        /*increase contrast (darker)*/
+        {                                                /*--------------------------*/
+            setting_contrast++;
+            if (setting_contrast > 0xFE)
+            {
+                setting_contrast = 0xFE;                /*upper limit*/
+           //     Lcd_XY_address(0,1);
+                printf(" Max. reached ");
+                DelayBigMs(350);
+            }
+            else
+            {
+   //             SetContrast();                            /*apply new setting*/
+             //   Lcd_XY_address(0,1);
+               // Lcd_ProgressBar((0xff-setting_contrast), 0x81);
+              //  SaveSettingsToEEPROM();                    /*save value to EEPROM*/
+                DelayBigMs(200);
+            }
+            OutputToRS232();                            /*set standard output to RS232*/
+            printf("\r\nLCD-Darker, contrast =%02x",setting_contrast);
+            OutputToLCD();                                /*set standard output to LCD*/
+        }        
+
+        if    (button_next == TRUE)                        /*info button*/
+        {
+            OutputToRS232();                            /*set standard output to RS232*/
+            printf("\r\nInfo button pressed");
+            OutputToLCD();                                /*set standard output to LCD*/
+       //     Lcd_clr();
+            HardWareTestMenu();
+         //   Lcd_clr();    
+            break;    
+        }
+    }
+}
+
+void HardWareTestMenu(void)
+{
+ //   Lcd_clr();
+ //   Lcd_XY_address(0,0);
+    printf("LED test");
+ //   Lcd_XY_address(0,2);
+    printf("IO & settings");
+//    Lcd_XY_address(0,4);
+    printf("Exit");
+    DelayBigMs(1000);
+    while(1)
+    {
+        ReadButtons();
+        if    (button_prev == TRUE)                        /*LED-test routines*/
+        {                                                /*-----------------*/
+  //          Lcd_clr();
+    //        Lcd_XY_address(5,2);
+            printf("OFF");
+            LED_GREEN = 0;
+            LED_RED = 0;
+            DelayBigMs(2000);
+      //      Lcd_XY_address(4,2);
+            printf("green");
+            LED_GREEN = 1;
+            LED_RED = 0;
+            DelayBigMs(2000);
+        //    Lcd_XY_address(4,2);
+            printf(" red ");
+            LED_GREEN = 0;
+            LED_RED = 1;
+            DelayBigMs(2000);
+          //  Lcd_XY_address(3,2);
+            printf("red+green");
+            LED_GREEN = 1;
+            LED_RED = 1;
+            DelayBigMs(2000);
+            LED_GREEN = 0;
+            LED_RED = 0;
+            break;    
+        }
+        
+        if    (button_select == TRUE)                        /*IO & settings*/
+        {                                                /*-------------*/
+
+    //        Lcd_XY_address(0,4);
+            printf("Contrast:%02X",setting_contrast);
+    //        Lcd_XY_address(0,5);
+            printf("PCBtimer:%05d",PCB_type_timer);
+
+    DelayBigMs(3000);
+            break;    
+        }        
+
+        if    (button_next == TRUE)                        /*Exit-button*/
+        {                                                 /*-----------*/
+            break;    
+        }
+    }
+}
+
+
+/*this routine wait for a card to be inserted, once inserted it will be initialised, when all is OK this routine will exit*/
+unsigned char CardStatus(void)
+{    
+    unsigned char err_code;
+
+    if(CARD_DETECT == 1)
+    {
+   //     Lcd_XY_address(4,1);
+    //    Lcd_CharBold();
+        printf("INSERT");
+   //     Lcd_XY_address(5,3);
+        printf("CARD");
+   //     Lcd_CharNormal();
+   //     Lcd_XY_address(0,5);
+        printf("  (20%02d%02d%02d)",RELEASE_VERSION,RELEASE_VERSION_SUB,RELEASE_VERSION_SUB_SUB);
+        DiskState = NO_CARD;    
+        return(FALSE);
+    }
+
+  //  Lcd_clr();
+ //   Lcd_XY_address(0,0);
+    printf("Card detected ");
+
+    //if(WR_PROTECT == 1)                        /*check if the SD-cards write protect "switch" has been set*/
+    //{
+    //    Lcd_XY_address(0,1);
+    //    printf("Card wr. prot.");
+    //    DiskState = NO_CARD;    
+    //    return(FALSE);
+    //}
+
+    DelayS(2);                                    /*do not access card immediatly, wait for card to stabelise*/
+//    Lcd_XY_address(0,1);
+    printf("Init. card:   ");
+//    Lcd_XY_address(0,2);                        /*set cursor to next line to print error messages*/
+    if (Init_Card_SPI())
+    {
+        DelayS(1);                                /*do not access card immediatly...*/
+        err_code = FindDrive();
+        if(err_code != TRUE)
+        {    
+  //          Lcd_XY_address(0,3);
+            switch(err_code)
+            {
+                case ERROR_ATAREAD_CMD17:
+                {
+                    printf("ATA:err. CMD17");        /*CMD17 does not respond, the command is not accepted...*/
+                    break;
+                }
+        
+                case ERROR_ATAREAD_TIMEOUT:
+                {
+                    printf("ATA:rd timeout");        /*timeout on waiting for start of data transfer*/
+                    break;
+                }
+
+                case ERROR_FAT_READBOOTSECTOR:
+                {
+                    printf("FAT:read boots");
+                    break;
+                }
+
+                case ERROR_FAT_JUMPOPCODE:
+                {
+                    printf("FAT:jump opcode");
+                    break;
+                }
+
+                case ERROR_FAT_BLOCKSIZE:
+                {
+                    printf("FAT:blocksize  ");
+                    break;
+                }
+
+                case ERROR_FAT_MEDIUM:
+                {
+                    printf("FAT:wr. medium ");
+                    break;
+                }
+        
+                default:
+                {
+                    printf("Undefined.....");
+                    break;
+                }
+            }
+    //        Lcd_XY_address(0,4);
+            printf("Card not supp.");
+        }
+        else
+        {
+      //      Lcd_XY_address(11,1);
+            printf("OK");
+            DiskState = CARD_ACTIVE;    
+            return(TRUE);
+        }
+    }
+    DelayS(4);                        /*when initialise failed wait before retry, otherwise the error message could not be read*/
+    DiskState = NO_CARD;    
+    return(FALSE);
+}
+
+
+/*initialise MMC/SD-card in SPI-mode*/
+unsigned char Init_Card_SPI(void)
+{
+    if (CARD_Init() == FALSE);                    /*The official initialisation routines as described in most of the documentation*/
+    {                                            /*If the official init fails, try the alternative init*/
+        if (CARD_AlternativeInit() == FALSE)    /*The alternative init, required ONLY because SanDisk does not follow the world's standards... <zucht>*/
+        {
+            return(FALSE);
+        }
+    }
+
+    Card_CID();                                    /*request Card - ID*/
+    Card_CSD();                                    /*request Card Specific Data*/
+
+    if (CARD_OperatingConditions(Response_data) == FALSE)
+    {
+        printf("CARD:err CMD58");            
+        return(FALSE);
+    }
+    else
+    {
+        if ((Response_data[2] & SUPPVOLT) != SUPPVOLT)    /*mask and compare for cards that support 3.0-3.1, 3.1-3.2, 3.2-3.3, 3.3-3.4 Volt*/
+        {
+            printf("CARD:voltage  ");
+            return(FALSE);
+        }
+
+        printf("CARD:OK       ");
+        return(TRUE);
+    }
+}
+
+/*This routine will count ALL files within the current directory (which could be root or subdirectory)*/
+void CountFiles(void)
+{
+    print_device_status("COUNTING FILES");    /*inform the user about a possible time consuming task*/
+
+    if (FileSearch(&file,0))                /*search for the first file on the card*/
+    {
+        CountedFiles = 1;
+        while (FileSearch(&file,1))            /*goto the next file*/
+        {
+            /*count ALL files (even the irrelevant files, since they do occupy diskspace, max 512 files in root you know)*/
+            CountedFiles++;                    /*increment file-counter*/
+        }
+        FileSearch(&file,0);                /*set the search routines back to the first file*/
+    }
+    else
+    {
+        CountedFiles = 0;
+    }
+
+  //  OutputToRS232();                                /*set standard output to RS232*/
+    printf("\r\nNumber of files in current (sub)dir: %d",CountedFiles);
+  //  OutputToLCD();                                    /*set standard output to LCD*/
+}
+
+/*This routine will 'filter' the currently 'selected' file,*/
+/*when the file does not meet the expected standards it returns 'FALSE'*/
+unsigned char FileFilter(void)
+{
+    /* Disk type                 | Size   */
+    /* --------------------------+--------*/
+    /* 35 track, no errors       | 174848 */
+    /* 35 track, 683 error bytes | 175531 */
+    /* 40 track, no errors       | 196608 */
+    /* 40 track, 768 error bytes | 197376 */
+
+    if((file.name[8] == 'P') && (file.name[9] == 'R') && (file.name[10] == 'G'))
+    {
+        return(PRG_FILE);
+    }
+
+    if ((file.name[8] == 'D') && (file.name[9] == '6') && (file.name[10] == '4'))
+    {
+        if (file.size == 174848)
+            return(D64_35T_MODE);
+
+        if  (file.size == 175531)
+            return(D64_35T_ER_MODE);
+
+        if (file.size == 196608)
+            return(D64_40T_MODE);
+
+        if (file.size == 177376)
+            return(D64_40T_ER_MODE);
+    }
+
+//    if((file.name[8] == 'T') && (file.name[9] == '6') && (file.name[10] == '4'))
+//    {
+//        return(T64_MODE);
+//    }
+
+    if ((file.size == 0) && (file.cluster!=0))    
+        return(SUBDIRECTORY);    /*normal subdirectories are files with a length 0 and only the rootdirectory points to cluster=0, meaning that subdirectories NEVER point to cluster 0*/
+
+    if ((file.name[0] == '.') && (file.name[1] == ' ') && (file.name[2] == ' ') && (file.name[3] == ' ') && (file.name[4] == ' ') && (file.name[5] == ' ') && (file.name[6] == ' ') && (file.name[7] == ' '))
+        return(SUBDIRECTORY);    /*this subdirectory points to the current directory*/
+
+    if ((file.name[0] == '.') && (file.name[1] == '.') && (file.name[2] == ' ') && (file.name[3] == ' ') && (file.name[4] == ' ') && (file.name[5] == ' ') && (file.name[6] == ' ') && (file.name[7] == ' '))
+        return(SUBDIRECTORY);    /*this subdirectory points to the parent directory (which could be root)*/
+
+    if ((file.name[0] != 0x20) && (file.name[8] == 0x20) && (file.name[9] == 0x20) && (file.name[10] == 0x20))
+        return(UNKNOWN);        /*when a filename has no extension, show it simply because it could be a file belonging to an IDE64 fixed game*/
+
+    return(FALSE);
+}
+
+/*this routine will search for the next available buffer, when no buffer can be found it responds with 255*/
+unsigned char SearchFreeBuffer(void)
+{
+    unsigned char lp;
+
+    lp=0;
+    while(lp<MAX_NUMBER_OF_DOS_BUFFERS)
+    {
+        if (DOS_buffer[lp].buffer_in_use == FALSE)    /*TRUE means that this channel is in use, FALSE means it is available*/
+        {
+            return(lp);                                /*return with the number of the available channel*/        
+        }
+        lp++;
+    }
+    return(255);                                    /*an error has occurred, there are no free channels left*/
+}
+
+/*****************************************************************************************************************/
+
+/*this routine will wait untill a string has been loaded that is terminated by an EOI*/
+void WaitForString(unsigned char *outputstring, unsigned frame_handshake)
+{
+    unsigned char cnt;
+
+    TimeOut = FALSE;
+    EOI = FALSE;
+    cnt = 0;
+    while((TimeOut == FALSE) && (EOI == FALSE))                /*get filename/instruction, this is all data untill an EOI is received*/
+    {
+        outputstring[cnt] = IEC_receive(frame_handshake);    /*save the received char to a string specified by the caller of this routine*/
+// printf("%02x", outputstring[cnt]);                        /*print string to be captured for debug purposes...*/
+        cnt++;
+    }
+    outputstring[cnt] = 0;    /*close the string with a "nul"*/
+}
+
+
+/*This routine will search for the first 'number' and puts this number into a register*/
+/*it returns 0 (FALSE) when the number does not fit into an unsigned char*/
+/*it returns the position of the character AFTER the number. so that this can be used for the next number search...*/
+unsigned char ValueFromString(unsigned char *inputstring, unsigned char *outputvalue)
+{
+    unsigned char lp;
+    
+    lp = 0;
+    *outputvalue = 0;
+
+    while ((inputstring[lp] < '0') || (inputstring[lp] > '9'))    /*check if this character is not a number*/    
+    { 
+        lp++;                        /*keep looping until a number is found*/
+        if (inputstring[lp] == 0)    /*when the end of the string has been reached, exit false*/
+        {
+            return(FALSE);            /*if there were no numbers at the beginning of this string, return FALSE*/        
+        }
+    }
+
+    while ((inputstring[lp] >= '0') && (inputstring[lp] <= '9'))    /*check if this character is a number*/    
+    { 
+        if (*outputvalue > 25)
+        {
+            return(FALSE);    /*the number in the string is larger the 255 and is not a 'unsigned char' exit routine*/
+        }
+        else
+        {
+            *outputvalue = *outputvalue * 10; 
+            *outputvalue = *outputvalue + (inputstring[lp] - '0');
+            lp++;
+        }
+    }
+
+    return(lp);        /*the first position directly after the number*/
+}
+
+
+/*This routine will search for the first 'number' and puts this number into a register*/
+/*the number has to start a the first character otherwise it returns false*/
+unsigned char LongValueFromString(unsigned char *inputstring, unsigned long *outputvalue)
+{
+    unsigned char lp;
+    
+    lp = 0;
+    *outputvalue = 0;
+
+    while ((inputstring[lp] >= '0') && (inputstring[lp] <= '9'))    /*check if this character is a number*/    
+    { 
+        *outputvalue = *outputvalue * 10; 
+        *outputvalue = *outputvalue + (inputstring[lp] - '0');
+        lp++;
+    }
+
+    return(lp);        /*the first position directly after the number*/
+}
+
+
+/*this routine extract the filename from the command string, it will remove all unwanted options and leaves the filename only    */
+/*Some of the possible entries to indicate the problem to be solved by this routine:                                            */
+/*normal open    : commandstring = "0:filename,s,r"                                                                                */
+/*simplified open: commandstring = "filename,s,r"                                                                                */
+/*simplified open: commandstring = "filename"                                                                                    */
+/*simplified open: commandstring = "0:filename"                                                                                    */
+/*replacement    : commandstring = "@0:filename,s,r"                                                                            */
+/*copy           : commandstring = "C0:backup=original"                                                                            */
+/*multiple copy  : commandstring = "COPY0:<destfile>=<sourcefile>" or "COPY:<destfile>=<sourcefile1>, <sourcefile2>, ..."        */
+/*therefore we may conclude that everything AFTER ':' and BEFORE ',' (or end-of-string) is the filename                            */
+void ExtractFilenameFromString(unsigned char *input_string, unsigned char *output_string)
+{
+    unsigned char tempstring[41];    
+
+    strcpy((char *)tempstring, (char *)input_string); /*this is required because the splitstring_on function destroys the inputvalues*/
+    if (!SplitStringOn_Sign(':', tempstring, output_string))    /*remove all characters BEFORE the ':'-sign*/
+    {                                                            /*if this succeeds the ':'-sign was found we can continue 'stripping' the string*/
+        strcpy((char *)output_string, (char *)input_string);                     /*when the commandstring does not contain a ':' the outputstring is empty, so we must fill it with the inputstring in order to continue*/    
+    }
+    SplitStringOn_Sign(',', output_string, tempstring);            /*remove all characters after the ','-sign and store the result in outputstring. If does not matter if this fails (because there is no ','-sign) because the outputstring is still correct. as it contains all caracters BEFORE the ','-sign (even if it isn't there*/
+}
+
+
+
+/*this routine will strip all characters before the given sign*/
+/*it will return the characters BEFORE the first sign in BEFORE_STRING (sign is not included in the result)*/
+/*it will return the characters AFTER the first sign in AFTER_STRING (sign is not included in the result)*/
+unsigned char SplitStringOn_Sign(unsigned char sign, unsigned char *beforesign_string, unsigned char *aftersign_string)
+{
+    unsigned char lp, lp2;
+    
+    lp = 0;
+    while(beforesign_string[lp])
+    {
+        if (beforesign_string[lp] == sign)
+        {    
+            lp++;
+            lp2 = 0;
+            while(beforesign_string[lp+lp2])
+            {
+                aftersign_string[lp2] = beforesign_string[lp+lp2];
+                lp2++;
+            }
+            beforesign_string[--lp] = 0;                            /*terminate the command_string, the :-sign is not included any more in te string*/
+            aftersign_string[lp2] = 0;                                /*terminate the copied string*/
+            return(TRUE);                                            /*indicate that the conversion (removal of all chars before :-sign) has succeeded*/
+        }
+        lp++;    
+    }
+    return(FALSE);                                                    /*indicate that the conversion (removal of all chars before :-sign) has failed*/
+}
+
+
+/*****************************************************************************************************************/
+
+/*this routine print some prefedined text to the display AND serial port*/
+void print_device_status(const unsigned char *message)
+{
+//    Lcd_XY_address(0,2);
+//    Lcd_CharBold();
+    printf("%s",message);
+//    Lcd_CharNormal();
+
+    OutputToRS232();                    /*set standard output to RS232*/
+    printf("\r\n%s",message);
+    OutputToLCD();                        /*set standard output to LCD*/
+}
+
+/*this routine print the name of the current file (which is suppost to be a D64 file)*/
+void print_D64_name(unsigned char mode)
+{
+    unsigned char i;
+
+    if (mode == INVERTED)                            /*depending on requested mode print in normal or inverse-mode*/
+//        Lcd_CharInvert();
+    
+//    Lcd_XY_address(0,0);
+    printf("%05d in dir. ",CountedFiles);            /*show the total number of files (sub)directory*/
+//    Lcd_XY_address(0,1);                            /*set cursor to line we want to use*/
+
+    if(file_type == NONE)
+    {
+        printf("%05d=        ",file_number);        /*show the current selection and clear the line*/
+//        Lcd_XY_address(6,1);                        /*set cursor back...*/                
+    }
+    else
+    {
+        printf("%05d=        ",file_number);        /*show the current selection and clear the line*/
+//        Lcd_XY_address(6,1);                        /*set cursor back...*/                
+        for(i=0;i<8;i++)                            /*print selection (or currently selected) 8.3-filename*/
+            putch(file.name[i]);                    /*character after character*/
+
+        OutputToRS232();                            /*output the same info to the serial port also*/
+        printf("\r\nfilename:");
+        for(i=0;i<8;i++)                            /*print selection (or currently selected) 8.3-filename*/
+            putch(file.name[i]);                    /*character after character*/
+        OutputToLCD();                                /*set standard output to LCD*/
+    }
+
+//    Lcd_CharNormal();
+//    Lcd_XY_address(0,5);
+    printf("%c=%02d ",0x0d,devicenumber);            /*print the device number on the display*/    
+    if(file_type == NONE)                            /*indicate on the display we are working in the root-dir of the card (HD-mode*/
+        printf("Hard-disk"); 
+    if(file_type == SUBDIRECTORY)                    /*indicate on the display we are working in the root-dir of the card (HD-mode*/
+        printf("Hard-disk"); 
+    if(file_type == PRG_FILE)                        /*...*/
+        printf("PRG-file "); 
+    if(file_type == UNKNOWN)                        /*...*/
+        printf("-UNKNOWN-"); 
+    if(file_type == D64_35T_MODE)                    /*indicate on the display the D64 file 35 tracks no errors*/
+        printf(".D64 35T "); 
+    if(file_type == D64_35T_ER_MODE)                /*indicate on the display the D64 file 35 tracks with errors*/
+        printf(".D64 35Te"); 
+    if(file_type == D64_40T_MODE)                    /*indicate on the display the D64 file 40 tracks no errors*/
+        printf(".D64 40T "); 
+    if(file_type == D64_40T_ER_MODE)                /*indicate on the display the D64 file 40 tracks with errors*/
+        printf(".D64 40Te"); 
+    if(file_type == T64_MODE)                        /*indicate on the display the T64*/
+        printf(".T64-mode");
+}
+
+/*this routine prints Track Sector and (remaining/loaded) blocks*/
+void print_D64_TSB(unsigned char trk, unsigned char sec, unsigned int blk, unsigned int total_blk)
+{
+    static unsigned char previous_track;
+    unsigned int blockcounter;
+
+    blockcounter = total_blk - blk;                                    /*calculate the current block*/
+
+  //  Lcd_XY_address(0,3);                                            /*set the LCD coordinates*/
+ //   Lcd_ProgressBar(blk, total_blk);                                /*draw a progress bar*/
+ //   Lcd_XY_address(0,4);                                            /*set the LCD coordinates*/
+    printf("%c=%02d T=%02d S=%02d",0x0e,error_code,trk,sec);        /*show the error code, track and sector*/
+
+    OutputToRS232();                                                /*output the same info to the serial port also*/
+    printf("\r\n%02d,%02d,%d/%d",trk,sec,blockcounter,total_blk);    /*send to serial the Track and sector info*/
+    OutputToLCD();                                                    /*set standard output to LCD*/
+
+    //Sound_TrackChange(trk-previous_track);                            /*play a sound (if required) of a moving head*/
+    previous_track = trk;                                            /*keep track of the number of tracks we move within the disk, this in order to simulate the sound properly*/
+}
+
+
+
+/*this routine is to be used to select a D64 image from the inserted card*/
+void SelectD64Image(void)
+{
+    unsigned char filefilter_result;
+    unsigned char blink_loop;
+
+    ReadButtons();
+    if    (button_prev == TRUE)
+    {
+        if (file_number == 1)
+        {
+            file_number=0;                                /*file counter is now '0' which means 'ROOT directory'*/
+            file_type = NONE;                            /*and because the user has selected root, the selected file_type = NONE*/
+        }
+        else
+        {
+            if (file_number > 1)
+            {
+                if (FileSearch(&file,2))                /*goto the previous D64 file*/
+                {
+                    file_number--;                        /*decrease selected file counter*/
+                }
+                filefilter_result = FileFilter();        /*check the selected file*/
+                file_type = filefilter_result;
+            }
+        }
+        DiskState = INVALID_POINTER;
+   //     Lcd_XY_address(0,3);
+    //    Lcd_SelectionBar((CountedFiles-file_number), CountedFiles);
+        print_D64_name(INVERTED);                        /*write the selection to display in inverted mode*/
+        DelayBigMs(BUTTON_SELECTION_RATE);                /*delay determines selection repetition rate*/
+    }
+
+    if    (button_next == TRUE)
+    {
+        if (file_number < CountedFiles)
+        {
+            if (file_number == 0)                        /*the first file on the card needs no search since it is allready found*/
+                file_number++;                            /*increase selected file counter*/
+            else
+                if (FileSearch(&file,1))                /*goto the next D64 file*/
+                    file_number++;                        /*increase selected file counter*/
+        }
+        filefilter_result = FileFilter();                /*check the selected file*/
+        file_type = filefilter_result;
+        DiskState = INVALID_POINTER;
+   //     Lcd_XY_address(0,3);
+  //      Lcd_SelectionBar((CountedFiles-file_number), CountedFiles);
+        print_D64_name(INVERTED);                        /*write the selection to display in inverted mode*/
+        DelayBigMs(BUTTON_SELECTION_RATE);                /*delay determines selection repetition rate*/
+    }
+
+    if    (button_select == TRUE)
+    {
+        filefilter_result = FileFilter();                /*check the selected file*/
+        file_type = filefilter_result;
+
+        if (file_number==0)                                /*file counter is now '0' which means 'ROOT directory'*/
+        {
+            file_type = NONE;                            /*and because the user has selected root, the selected file_type = NONE*/
+    //        Lcd_XY_address(0,2);                        /*set cursor*/        
+            printf("              ");                    /*clear the file_info information*/
+            print_D64_name(PLAIN);                        /*write the selection to display in normal-mode*/
+            DiskState = CARD_ACTIVE;                    /*the 1541-III is now functioning as a harddisk*/
+            DelayBigMs(BUTTON_SELECTION_RATE);            /*delay determines selection repetition rate*/
+        }
+        else
+        {
+            if (filefilter_result == SUBDIRECTORY)
+            {
+                OpenSubDirectory(&file);                    /*the user request to enter a subdirectory, so we call the routine that setts all registers in the correct way in order to use subdirectories properly*/
+                file_number = 0;                            /*the file_number counter needs to be reset*/
+                file_type = NONE;                            /*and because the user has selected a (sub)directory, the selected file_type = NONE, as there is no image file selected and we are operating in harddiskmode*/
+    
+                print_D64_name(PLAIN);                        /*write the selection to display in normal-mode, this clears up the display, but with the incorrect filecount values*/
+                CountFiles();                                /*count all files in the opened directory*/
+                print_D64_name(PLAIN);                        /*write the selection to display in normal-mode, the countvalues are updated*/
+      //          Lcd_XY_address(0,2);                        /*set cursor*/        
+                printf("              ");                    /*clear the file_info information*/
+                DiskState = CARD_ACTIVE;                    /*the 1541-III is now functioning as a harddisk*/
+                DelayBigMs(BUTTON_SELECTION_RATE);            /*delay determines selection repetition rate*/
+            }
+            else
+            {
+                if ((filefilter_result != PRG_FILE) && (filefilter_result != UNKNOWN))    /*pass all supported D64 files and leave out PRG and unknown files*/
+                {
+                    FileSectorScan(&file);                    /*update the sector location table cache*/
+                    D64ReadBAM();                            /*update the BAM*/
+                    DiskState = CARD_ACTIVE;                /*the 1541-III is now accessable*/
+        //            Lcd_XY_address(0,2);                    /*set cursor*/        
+                    printf("              ");                /*clear the file_info information*/
+                    print_D64_name(PLAIN);                    /*write the selection to display in normal-mode*/
+                }
+                else
+                {
+                    for (blink_loop=4;blink_loop>0;blink_loop--)    /*create a blinking effect to draw attention to this line*/
+                    {    
+          //              Lcd_CharInvert();                                
+            //            Lcd_XY_address(0,1);
+                        printf("Selection err.");
+                        DelayBigMs(250);                    /*delay to make sure the message can be read properly*/        
+              //          Lcd_CharNormal();
+                //        Lcd_XY_address(0,1);
+                        printf("Selection err.");
+                        DelayBigMs(250);                    /*delay to make sure the message can be read properly*/        
+                    }
+                    print_D64_name(INVERTED);                /*write the selection to display in inverted mode*/
+                }
+            }
+        }
+    }
+}
+
+/*****************************************************************************************************************/
+/*almost identical to loading a directory (seen from a C64)*/
+/*This routine shows 'all' the files on the card*/
+
+/*Note: 'all' means the files that are OK according the filefilter routine*/
+void CardDirectory(void)
+{
+    unsigned pass_counter;
+    unsigned char separation_line=FALSE;
+    unsigned char filefilter_result;
+    unsigned int index_cnt;
+    unsigned char lp;
+    unsigned char dir_width;
+    unsigned int blocksize;
+
+    SetErrorCode(0,LED_ON);        /*unless we fail we will exit with no error*/
+    EOI = FALSE;
+    IEC_turnaround();            /*we now SEND data to the bus so... make our device a talker*/
+
+    /*----------------*/
+    /*directory header*/
+    /*----------------*/        
+    IEC_send(0x01);                /*load this "program" to start address 0x0401*/
+    IEC_send(0x04);
+
+    if (VIC20_mode == TRUE)        /*for better readabillity on a VIC-20 the card directory is displayed in a smallscreen and a widescreen version*/    
+    {                            /*                                                                                                       |              |*/ /*useable area of a VC-20 dir line*/
+        dir_width = 10;            /*the number of places that a VIC20 file entry may occupy in order to fit the screen width of 22 chars*/
+        IEC_send(0x01);    IEC_send(0x01);    IEC_send(0x00);    IEC_send(0x00);    IEC_send(0x20); IEC_send(0x12); IEC_send(0x20);    IEC_send(0x22); IEC_send_string("CARD DIRECTORY"); IEC_send(0x22); IEC_send(0x00);    /*VIC-20 Directory header*/
+        IEC_send(0x01);    IEC_send(0x01);    IEC_send(0x00);    IEC_send(0x00); IEC_send(0x20);    IEC_send(0x20);    IEC_send(0x22);    IEC_send_string("u``````````i"); IEC_send(0x22); IEC_send(0x00);    /*top-line*/
+        IEC_send(0x01);    IEC_send(0x01);    IEC_send(0x00);    IEC_send(0x00); IEC_send(0x20);    IEC_send(0x20);    IEC_send(0x22);    IEC_send_string("} 1541-III }"); IEC_send(0x22); IEC_send(0x00);    /*model*/
+        IEC_send(0x01);    IEC_send(0x01);    IEC_send(0x00);    IEC_send(0x00); IEC_send(0x20);    IEC_send(0x20);    IEC_send(0x22);    IEC_send_string("}J. DEROGEE}"); IEC_send(0x22); IEC_send(0x00);    /*credits*/
+        IEC_send(0x01);    IEC_send(0x01);    IEC_send(0x00);    IEC_send(0x00); IEC_send(0x20);    IEC_send(0x20);    IEC_send(0x22);    IEC_send_string("}VIC20-MODE}"); IEC_send(0x22); IEC_send(0x00);    /*credits*/
+        IEC_send(0x01);    IEC_send(0x01);    IEC_send(0x00);    IEC_send(0x00); IEC_send(0x20);    IEC_send(0x20);    IEC_send(0x22);    IEC_send_string("j``````````k"); IEC_send(0x22); IEC_send(0x00);    /*separation-line*/
+    }
+    else
+    {
+        dir_width = 17;            /*the number of places that a C64/C128/C16 etc. file entry may occupy in order to fit the screen width of 40 chars*/
+        IEC_send(0x01);    IEC_send(0x01);    IEC_send(0x00);    IEC_send(0x00);    IEC_send(0x20); IEC_send(0x12); IEC_send(0x20);    IEC_send(0x22); IEC_send_string(" CARD DIRECTORY "); IEC_send(0x22); IEC_send_string(" 00 2A"); IEC_send(0x00);    /*Normal Directory header*/
+        IEC_send(0x01);    IEC_send(0x01);    IEC_send(0x00);    IEC_send(0x00); IEC_send(0x20); IEC_send(0x20);    IEC_send(0x22);    IEC_send_string("u````````````````i"); IEC_send(0x22); IEC_send(0x00);    /*top-line*/
+        IEC_send(0x01);    IEC_send(0x01);    IEC_send(0x00);    IEC_send(0x00); IEC_send(0x20); IEC_send(0x20);    IEC_send(0x22);    IEC_send_string("} 1541-III MBED  }"); IEC_send(0x22); IEC_send(0x00);    /*model*/
+        IEC_send(0x01);    IEC_send(0x01);    IEC_send(0x00);    IEC_send(0x00); IEC_send(0x20); IEC_send(0x20);    IEC_send(0x22);    IEC_send_string("}J.DEROGEE & KGE }"); IEC_send(0x22); IEC_send(0x00);    /*credits*/
+        IEC_send(0x01);    IEC_send(0x01);    IEC_send(0x00);    IEC_send(0x00); IEC_send(0x20); IEC_send(0x20);    IEC_send(0x22);    IEC_send_string("j````````````````k"); IEC_send(0x22); IEC_send(0x00);    /*separation-line*/
+    }
+
+    /*-----------------*/
+    /*directory content*/
+    /*-----------------*/
+
+    pass_counter = 0;
+    index_cnt = 0;    
+    while(pass_counter++ < 3)
+    {
+        if (pass_counter != 1)            /*print a seperator line BETWEEN the different file types, pass_counter 1 means the first and between means ALL EXCEPT 1 (because thee is nothing before 1, so the line could bever be in between)*/
+            separation_line = FALSE;
+
+        if(FileSearch(&file,0))
+        {                    
+            do                
+            {            
+    //OutputToRS232();                                                        /*set standard output to RS232*/
+    //printf("\r\n8.3:%c%c%c%c%c%c%c%c",file.name[0],file.name[1],file.name[2],file.name[3],file.name[4],file.name[5],file.name[6],file.name[7]);        /*for debug purposes only !!!*/
+    //printf("\r\nlfn:%c%c%c%c%c%c%c%c%c%c%c%c",file.name_lfn[0],file.name_lfn[1],file.name_lfn[2],file.name_lfn[3],file.name_lfn[4],file.name_lfn[5],file.name_lfn[6],file.name_lfn[7],file.name_lfn[8],file.name_lfn[9],file.name_lfn[10],file.name_lfn[11]);        /*for debug purposes only !!!*/
+    //OutputToLCD();                                                            /*set standard output to LCD*/
+    
+                print_D64_TSB(0, 0, (3*CountedFiles-index_cnt), 3*CountedFiles);    /*print track, sector and progress bar, since were are making 3 passes, the counter is used 3 times (3 passes)*/
+                index_cnt++;    /*for the best results... arrange the files on filetype, directories first, the D64's of all types, then PRG-files*/
+                filefilter_result = FileFilter();
+                if ((pass_counter == 1) && (filefilter_result == SUBDIRECTORY) ||
+                    ((pass_counter == 2) && ((filefilter_result == D64_35T_MODE) || (filefilter_result == D64_35T_ER_MODE) || (filefilter_result == D64_40T_MODE) || (filefilter_result == D64_40T_ER_MODE))) ||
+                    ((pass_counter == 3) && ((filefilter_result == PRG_FILE) || (filefilter_result == T64_MODE) || (filefilter_result == UNKNOWN))))
+                {
+                    if (separation_line == FALSE)        /*for better readabillity... add a small separation-line (but only if required)*/    
+                    {
+                        separation_line = TRUE;
+                        IEC_send(0x01);    IEC_send(0x01);    IEC_send(0x00);    IEC_send(0x00);    IEC_send(0x20);    IEC_send(0x20); IEC_send(0x22);
+                        for(lp=0;lp<(dir_width+1);lp++)
+                            IEC_send('`');
+                         IEC_send(0x22); IEC_send(0x00);
+                    }
+
+                    IEC_send(0x01);
+                    IEC_send(0x01);
+
+                    if (pass_counter == 3)                /*in the third pass we show all the file information, as these are not images or directories, but actual files*/
+                    {
+                        blocksize = file.size / 254;    /*calculate blocksize(1 block=254 bytes) from filesize(bytes)*/
+                        IEC_send(blocksize%256);        /*low-byte of blocksize of file*/
+                        IEC_send(blocksize/256);        /*high-byte of  blocksize of file*/
+                        if(blocksize < 10)                /*if required, add extra space for better allignment*/
+                            IEC_send(0x20);    
+            
+                        if(blocksize < 100)                /*if required, add extra space for better allignment*/
+                            IEC_send(0x20);    
+                    }
+                    else
+                    {
+                        IEC_send(0);                    /*low-byte of blocksize of file*/
+                        IEC_send(0);                    /*high-byte of blocksize of file*/
+                        IEC_send(0x20);    
+                        IEC_send(0x20);    
+                    }
+
+                    IEC_send(0x22);                 /*each entry must be starting with the "-sign*/
+                    if ((filefilter_result != PRG_FILE) && (filefilter_result != UNKNOWN))
+                        IEC_send('$');                /*proceed each image (.D64 or similar) or subdirectory with a $-sign, to indicate that it has to be loaded as an directory*/
+    
+                    if(file.name_lfn[0] == 0)        /*check if this entry has an 8.3-name or LFN-name*/
+                    {            
+                        IEC_send(file.name[0]);        /*8.3 filename WITHOUT the extra spaces (looks much better as the LFN has the same look by nature)*/
+                        lp=7;
+                        if(((file.name[1]) != ' ') || ((file.name[2]) != ' ') || ((file.name[3]) != ' ') || ((file.name[4]) != ' ') || ((file.name[5]) != ' ') || ((file.name[6]) != ' ') || ((file.name[7]) != ' '))
+                        {    IEC_send(file.name[1]);    lp=6;}
+                        if(((file.name[2]) != ' ') || ((file.name[3]) != ' ') || ((file.name[4]) != ' ') || ((file.name[5]) != ' ') || ((file.name[6]) != ' ') || ((file.name[7]) != ' '))
+                        {    IEC_send(file.name[2]);    lp=5;}
+                        if(((file.name[3]) != ' ') || ((file.name[4]) != ' ') || ((file.name[5]) != ' ') || ((file.name[6]) != ' ') || ((file.name[7]) != ' '))
+                        {    IEC_send(file.name[3]);    lp=4;}
+                        if(((file.name[4]) != ' ') || ((file.name[5]) != ' ') || ((file.name[6]) != ' ') || ((file.name[7]) != ' '))
+                        {    IEC_send(file.name[4]);    lp=3;}
+                        if(((file.name[5]) != ' ') || ((file.name[6]) != ' ') || ((file.name[7]) != ' '))
+                        {    IEC_send(file.name[5]);    lp=2;}
+                        if(((file.name[6]) != ' ') || ((file.name[7]) != ' '))
+                        {    IEC_send(file.name[6]);    lp=1;}
+                        if((file.name[7]) != ' ')
+                        {    IEC_send(file.name[7]);    lp=0;}
+    
+                        lp = (dir_width - 7) + lp;                    /*calculate the remaining spaces to fit the VIC20 mode*/
+                    }
+                    else
+                    {
+                        for(lp=0;lp<(dir_width-1);lp++)                /*print the LFN string*/
+                        {
+                            IEC_send(file.name_lfn[lp]);
+                            if ((file.name_lfn[lp+1] == '.') && (file.name_lfn[lp+5] == 0))        /*print the string, BUT without the last for characters (but only for files with a 3 letter extension, which are the .D64, .PRG, etc)*/                    
+                                break;
+
+                            if (file.name_lfn[lp+1] == 0)            /*otherwise on end of string, stop*/                    
+                                break;
+                        }                        
+    
+                        if (lp==(dir_width-1))                        /*check if the filename was displayed partially, if so, then add a *-sign*/                    
+                            IEC_send('*');                            /*the max ammount of displayable characters was printed, but there where more characters to print, so we add a *-sign to keep compatible with the search routines*/
+    
+                        lp = dir_width  - lp;                        /*calculate the remaining number of spaces*/
+                    }
+                
+                    IEC_send(0x22);                                    /*each entry must end with the "-sign*/
+                    if (filefilter_result == PRG_FILE)
+                        lp++;                                        /*since this entry did not start with the $-sign, we must add an extra space at the end to keep length of each line identical*/
+    
+                    while(lp--)                                        /*the remaining location must be filled with spaces*/
+                        IEC_send(' ');
+    
+                    switch (filefilter_result)
+                    {        
+                        case PRG_FILE:
+                        {
+                            IEC_send('P');                            /*print PRG*/
+                            IEC_send('R');
+                            IEC_send('G');
+                            break;
+                        }
+
+                        case D64_35T_MODE:;
+                          case D64_35T_ER_MODE:;
+                        case D64_40T_MODE:;    
+                        case D64_40T_ER_MODE:
+                        {
+                            IEC_send('D');                            /*print D64*/
+                            IEC_send('6');
+                            IEC_send('4');
+                            break;
+                        }
+
+                        case T64_MODE:
+                        {
+                            IEC_send('T');                            /*print T64*/
+                            IEC_send('6');
+                            IEC_send('4');
+                            break;
+                        }
+
+                        case SUBDIRECTORY:
+                        {
+                            IEC_send('D');                            /*print DIR*/
+                            IEC_send('I');
+                            IEC_send('R');
+                            break;
+                        }
+
+                        default:
+                        {
+                            break;                                    /*print nothing*/
+                        }
+                    }
+    
+                    IEC_send(0x00);
+                }
+            }
+            while(FileSearch(&file,1));
+        }
+    }
+
+    FileSearch(&file,0);                    /*select the first file on the card, this to please all other routines using the filesearch() routine, this since selected_D64file is set to 0*/
+
+    /*PROPERLY END THIS DIRECTORY, BUT DO NOT PRINT THE FREE BLOCKS TEXT... IT WOULD NOT MAKE ANY SENSE, since the limitation is in the 512 files in root-dir limit*/
+    IEC_send(0x00);
+    EOI = TRUE;                                /*indicate the last byte*/
+    IEC_send(0x00);
+    IEC_undoturnaround();                    /*were done talking towards the bus*/
+    SetErrorCode(0, LED_OFF);                /*all is OK, set the LED blinking mode to 'RITHM' to indicate that we have done somthing on a higher level then something within a D64-file*/
+}
+
+
+void D64Directory(void)
+{
+    unsigned char lp, mode, extra_spaces, track, sector, unused;
+    unsigned int blocksize, blocksfree, read_blocks;
+
+    SetErrorCode(0,LED_ON);         /*unless we fail we will exit with no error*/
+    EOI = FALSE;
+    IEC_turnaround();                /*we now SEND data to the bus so... make our device a talker*/
+
+    /*some bytes required for sending a directory entry to a VIC20, C64, C128, etc.*/
+    IEC_send(0x01);                    /*load this "program" to start address 0x0401*/
+    IEC_send(0x04);
+
+/*Directory header*/
+/*----------------*/
+    D64BlockRead(18,0);
+    read_blocks = 1;
+    print_D64_TSB(18,0,read_blocks, 0);
+    IEC_send(0x01);                    /*...*/
+    IEC_send(0x01);                    /*...*/
+    IEC_send(0);        /*drive-number of this device, in the beginning of this project used as file pointer/indicator*/
+    IEC_send(0);        /*drive-number of this device, in the beginning of this project uses as file pointer/indicator*/
+    IEC_send(0x12);                    /*RVS-ON (invert characters)*/
+    IEC_send(0x22);                    /*"-sign*/
+    for(lp=144;lp<160;lp++)
+    {
+        IEC_send(RAM_buffer[lp]);    /*send the Diskname*/
+    }
+
+    IEC_send(0x22);                    /*"-sign*/
+    IEC_send(0x20);                    /*space*/
+    IEC_send(RAM_buffer[162]);        /*send the disk-ID byte-0*/
+    IEC_send(RAM_buffer[163]);        /*send the disk-ID byte-1*/
+    IEC_send(0x20);                    /*space*/
+    IEC_send(RAM_buffer[165]);        /*send the DOS-version and format-type byte-0*/
+    IEC_send(RAM_buffer[166]);        /*send the DOS-version and format-type byte-1*/
+    IEC_send(0x00);                    /*a byte indicating the end of this "directory-line"*/
+
+/*Directory entry ...*/
+/*-------------------*/
+    mode=0;    /*set sector read to first entry*/
+    while(D64SeekDirEntry(mode, &track, &sector, &unused))        /*get directory entry and request the current track and sector*/
+    {
+        mode=1;    /*set sector read to next entry*/
+        print_D64_TSB(track,sector,read_blocks,0);
+        if (dir_entry.filetype != 0x00)                 /*scratched files are NOT displayed in the directory*/    
+        {
+            IEC_send(0x01);                                /*bytes indicating the beginning of a "directory-line"*/
+            IEC_send(0x01);
+            IEC_send(dir_entry.blocksize_low_byte);        /*size of this file low-byte*/
+            IEC_send(dir_entry.blocksize_high_byte);    /*size of this file high-byte*/
+//    dir_entry.record_size_relfile = 0x00;
+            blocksize = ((256 * dir_entry.blocksize_high_byte) + dir_entry.blocksize_low_byte);
+            if (blocksize < 10)                            /*add an extra space(s) to adjust line length*/
+                IEC_send(0x20);                            /*                                           */
+            if (blocksize < 100)                        /*                                           */
+                IEC_send(0x20);                            /*                                           */
+            if (blocksize < 1000)                        /*                                           */
+                IEC_send(0x20);                            /*                                           */
+            IEC_send(0x22);                                /*"-sign*/
+            
+            extra_spaces = 0;
+            for(lp=0;lp<16;lp++)
+            {
+                if(dir_entry.filename[lp]== 160)
+                    extra_spaces++;
+                else
+                    IEC_send(dir_entry.filename[lp]);        /*filename of this entrynumber*/
+
+            }
+
+            IEC_send(0x22);                            /*"-sign*/
+            while(extra_spaces != 0)
+            {
+                IEC_send(0x20);                        /*add some extra spaces for proper allignment*/
+                extra_spaces--;
+            }
+
+            /*filetype*/
+            /*--------*/
+            if (dir_entry.filetype > 127)            /*when MSB has been set the file has been properly closed*/    
+                IEC_send(0x20);                        /*print a space before the filetype*/
+            else
+                IEC_send(0x2A);                        /*print a asterix before the filetype to indicate that the file has not been closed (yet)*/
+    
+            switch (0x07 & dir_entry.filetype)        /*the type of file is stored in the first byte (MSB is file open/closed, 3 lowest bits are of interest here ...*/
+            {
+                case 0:
+                {
+                    IEC_send(0x44);                    /*file type = DELeted */
+                    IEC_send(0x45);
+                    IEC_send(0x4C);
+                    break;
+                }
+    
+                case 1:
+                {
+                    IEC_send(0x53);                    /*file type = SEQuential */
+                    IEC_send(0x45);
+                    IEC_send(0x51);
+                    break;
+                }
+    
+                case 2:
+                {
+                    IEC_send(0x50);                    /*file type = PRoGram */
+                    IEC_send(0x52);
+                    IEC_send(0x47);
+                    break;
+                }
+    
+                case 3:
+                {
+                    IEC_send(0x55);                    /*file type = USeR */
+                    IEC_send(0x53);
+                    IEC_send(0x52);
+                    break;
+                }
+    
+    
+                case 4:
+                {
+                    IEC_send(0x52);                    /*file type = RELative */
+                    IEC_send(0x45);
+                    IEC_send(0x4C);
+                    break;
+                }
+    
+                default:
+                {
+                    IEC_send(0x55);                    /*file type = UNKnown (is only shown if someone uses these values out of spec...*/
+                    IEC_send(0x4E);
+                    IEC_send(0x4B);
+                    break;
+                }
+            }
+        
+            if (dir_entry.filetype > 191)
+                IEC_send(0x3C);                        /*print a "<" to indicate a locked file*/
+            else
+                IEC_send(0x20);
+
+            IEC_send(0x20);
+            IEC_send(0x20);
+            IEC_send(0x20);
+            IEC_send(0x00);
+        }
+    }
+
+/*Blocks free "directory-line"*/
+/*----------------------------*/
+    IEC_send(0x01);
+    IEC_send(0x01);
+    blocksfree = D64LoadFreeBlocks();        /*read the number of free blocks from the D64 file*/
+    IEC_send(blocksfree%256);                /*low-byte of free blocks value*/
+    IEC_send(blocksfree/256);                /*high-byte of free blocks value*/
+    IEC_send_string("BLOCKS FREE.               ");    /*"Blocks free."*/
+    IEC_send(0x00);
+    IEC_send(0x00);
+    EOI = TRUE;                                /*indicate the last byte*/
+    IEC_send(0x00);
+    IEC_undoturnaround();                    /*were done talking towards the bus*/
+    SetErrorCode(0, LED_OFF);                /*all is OK*/
+}
+
+void T64Directory(void)
+{
+    unsigned char lp, mode, extra_spaces, track, sector, unused;
+    unsigned int blocksize, blocksfree, read_blocks;
+
+    SetErrorCode(0,LED_ON);         /*unless we fail we will exit with no error*/
+    EOI = FALSE;
+    IEC_turnaround();                /*we now SEND data to the bus so... make our device a talker*/
+
+    /*some bytes required for sending a directory entry to a VIC20, C64, C128, etc.*/
+    IEC_send(0x01);                    /*load this "program" to start address 0x0401*/
+    IEC_send(0x04);
+
+/*Directory header*/
+/*----------------*/
+    D64BlockRead(18,0);
+    read_blocks = 1;
+    print_D64_TSB(18,0,read_blocks, 0);
+    IEC_send(0x01);                    /*...*/
+    IEC_send(0x01);                    /*...*/
+    IEC_send(0);        /*drive-number of this device, in the beginning of this project used as file pointer/indicator*/
+    IEC_send(0);        /*drive-number of this device, in the beginning of this project uses as file pointer/indicator*/
+    IEC_send(0x12);                    /*RVS-ON (invert characters)*/
+    IEC_send(0x22);                    /*"-sign*/
+    for(lp=144;lp<160;lp++)
+    {
+        IEC_send(RAM_buffer[lp]);    /*send the Diskname*/
+    }
+
+    IEC_send(0x22);                    /*"-sign*/
+    IEC_send(0x20);                    /*space*/
+    IEC_send(RAM_buffer[162]);        /*send the disk-ID byte-0*/
+    IEC_send(RAM_buffer[163]);        /*send the disk-ID byte-1*/
+    IEC_send(0x20);                    /*space*/
+    IEC_send(RAM_buffer[165]);        /*send the DOS-version and format-type byte-0*/
+    IEC_send(RAM_buffer[166]);        /*send the DOS-version and format-type byte-1*/
+    IEC_send(0x00);                    /*a byte indicating the end of this "directory-line"*/
+
+/*Directory entry ...*/
+/*-------------------*/
+    mode=0;    /*set sector read to first entry*/
+    while(D64SeekDirEntry(mode, &track, &sector, &unused))        /*get directory entry and request the current track and sector*/
+    {
+        mode=1;    /*set sector read to next entry*/
+        print_D64_TSB(track,sector,read_blocks,0);
+        if (dir_entry.filetype != 0x00)                 /*scratched files are NOT displayed in the directory*/    
+        {
+            IEC_send(0x01);                                /*bytes indicating the beginning of a "directory-line"*/
+            IEC_send(0x01);
+            IEC_send(dir_entry.blocksize_low_byte);        /*size of this file low-byte*/
+            IEC_send(dir_entry.blocksize_high_byte);    /*size of this file high-byte*/
+//    dir_entry.record_size_relfile = 0x00;
+            blocksize = ((256 * dir_entry.blocksize_high_byte) + dir_entry.blocksize_low_byte);
+            if (blocksize < 10)                            /*add an extra space(s) to adjust line length*/
+                IEC_send(0x20);                            /*                                           */
+            if (blocksize < 100)                        /*                                           */
+                IEC_send(0x20);                            /*                                           */
+            if (blocksize < 1000)                        /*                                           */
+                IEC_send(0x20);                            /*                                           */
+            IEC_send(0x22);                                /*"-sign*/
+            
+            extra_spaces = 0;
+            for(lp=0;lp<16;lp++)
+            {
+                if(dir_entry.filename[lp]== 160)
+                    extra_spaces++;
+                else
+                    IEC_send(dir_entry.filename[lp]);        /*filename of this entrynumber*/
+
+            }
+
+            IEC_send(0x22);                            /*"-sign*/
+            while(extra_spaces != 0)
+            {
+                IEC_send(0x20);                        /*add some extra spaces for proper allignment*/
+                extra_spaces--;
+            }
+
+            /*filetype*/
+            /*--------*/
+            if (dir_entry.filetype > 127)            /*when MSB has been set the file has been properly closed*/    
+                IEC_send(0x20);                        /*print a space before the filetype*/
+            else
+                IEC_send(0x2A);                        /*print a asterix before the filetype to indicate that the file has not been closed (yet)*/
+    
+            switch (0x07 & dir_entry.filetype)        /*the type of file is stored in the first byte (MSB is file open/closed, 3 lowest bits are of interest here ...*/
+            {
+                case 0:
+                {
+                    IEC_send(0x44);                    /*file type = DELeted */
+                    IEC_send(0x45);
+                    IEC_send(0x4C);
+                    break;
+                }
+    
+                case 1:
+                {
+                    IEC_send(0x53);                    /*file type = SEQuential */
+                    IEC_send(0x45);
+                    IEC_send(0x51);
+                    break;
+                }
+    
+                case 2:
+                {
+                    IEC_send(0x50);                    /*file type = PRoGram */
+                    IEC_send(0x52);
+                    IEC_send(0x47);
+                    break;
+                }
+    
+                case 3:
+                {
+                    IEC_send(0x55);                    /*file type = USeR */
+                    IEC_send(0x53);
+                    IEC_send(0x52);
+                    break;
+                }
+    
+    
+                case 4:
+                {
+                    IEC_send(0x52);                    /*file type = RELative */
+                    IEC_send(0x45);
+                    IEC_send(0x4C);
+                    break;
+                }
+    
+                default:
+                {
+                    IEC_send(0x55);                    /*file type = UNKnown (is only shown if someone uses these values out of spec...*/
+                    IEC_send(0x4E);
+                    IEC_send(0x4B);
+                    break;
+                }
+            }
+        
+            if (dir_entry.filetype > 191)
+                IEC_send(0x3C);                        /*print a "<" to indicate a locked file*/
+            else
+                IEC_send(0x20);
+
+            IEC_send(0x20);
+            IEC_send(0x20);
+            IEC_send(0x20);
+            IEC_send(0x00);
+        }
+    }
+
+/*Blocks free "directory-line"*/
+/*----------------------------*/
+    IEC_send(0x01);
+    IEC_send(0x01);
+    blocksfree = D64LoadFreeBlocks();        /*read the number of free blocks from the D64 file*/
+    IEC_send(blocksfree%256);                /*low-byte of free blocks value*/
+    IEC_send(blocksfree/256);                /*high-byte of free blocks value*/
+    IEC_send_string("BLOCKS FREE.               ");    /*"Blocks free."*/
+    IEC_send(0x00);
+    IEC_send(0x00);
+    EOI = TRUE;                                /*indicate the last byte*/
+    IEC_send(0x00);
+    IEC_undoturnaround();                    /*were done talking towards the bus*/
+    SetErrorCode(0, LED_OFF);                /*all is OK*/
+}
+
+
+/*this routine will search for a file ON THE CARD that matches the given filename search pattern*/
+/*the return value (if file is found) will be the index-number of the file as stored on the card*/
+unsigned int SeekFileOnCard(unsigned char *filename, struct file2TYPE *file)
+{
+    signed char lp;
+    unsigned int index;
+    
+    index = 0;                    /*reset the index counter, as we do whish to know what the index of this file (within this (sub)directory) is*/
+     if (!FileSearch(file, 0))    /*search for the first file on the card. Attention: screws up secbuf!!*/
+        return(FALSE);
+     while(1)
+    {
+        index++;
+         lp = -1;        /*reset loopcounter*/
+        if (FileFilter() != FALSE)                        /*files that are not recognized by the filefilter will be excluded from the search. Simply because these files are not shown to user when he/she requests the cards directory*/
+        {
+            if(file->name_lfn[0] == 0)                    /*check if this entry has an 8.3-name or LFN-name*/
+            {        /*this file has no LFN name so we must use the 8.3 information for further searching*/
+                do    /*----------------------------------------------------------------------------------*/
+                {
+                    lp++;
+                //    OutputToRS232();                                                    /*set standard output to RS232*/
+                //    printf("\r\n8.3:lp=%02X, %c, %c",lp, file->name[lp], filename[lp]);    /*for debug purposes only !!!*/
+                //    OutputToLCD();                                                        /*set standard output to LCD*/
+        
+                    if((filename[lp] == 0) && (lp==8))    /*when we've succesfully matched all 8 chars of the 8.3 name... we have a match*/
+                        return(index);                    /*all the remaining characters of the current file are spaces, we have a match!!!*/    
+
+                    if(filename[lp] == 0)                /*when we have reached end of the searched filename but the current file has more characters then check if all further characters of file are spaces*/
+                        while(lp<8)
+                        {
+                            if (file->name[lp] != ' ')
+                                break;
+                            if (lp==7)
+                                return(index);                /*all the remaining characters of the current file are spaces, we have a match!!!*/    
+                            lp++;
+                        }
+
+                    if(filename[lp] == 0)                 /*when the search string has not been ended but the searched filename has... no match*/
+                        break;                            /*we have no match*/
+                
+                    /*wildcard filter*/
+                    if (filename[lp] == '?')            /*when we encounter an '?', it does not matter what the real char of the filename is*/
+                        file->name[lp] = '?';            /*therefore we can replace the real char by a '?' so that the comparison (at the end of this loop) can still be valid*/
+            
+                    if (filename[lp] == '*')            /*when we have come so far and detected a * in our search string... we may consider this a match*/
+                        return(index);                        /*we have a partial or possible 100% match... but good enough to return with TRUE*/
+                }
+                while(file->name[lp] == filename[lp]);    /*do the compare of current char of both strings*/
+            }
+            else    /*this file has an LFN entry, use this for searching*/
+            {        /*--------------------------------------------------*/
+                do
+                {
+                    lp++;
+                //    OutputToRS232();                                                        /*set standard output to RS232*/
+                //    printf("\r\nLFN:lp=%02X, %c, %c",lp, file->name_lfn[lp], filename[lp]);    /*for debug purposes only !!!*/
+                //    OutputToLCD();                                                            /*set standard output to LCD*/
+
+                    if((filename[lp] == 0) && (file->name_lfn[lp]== '.'))    /*when we have reached the extension if the file, we may consider this a match*/
+                        return(index);                            /*we have a match and we may asume that the extension is correct as well because the filefilter has allready checked this as a OK file, so how big is the chance that there are a .PRG and a .D64 with identical names ?!?!*/
+
+                    if((filename[lp] == 0) && (file->name_lfn[lp]== 0))    /*when we have reached the end of both strings, this is the perfect match*/
+                        return(index);                            /*we have a match and we may asume that the extension is correct as well because the filefilter has allready checked this as a OK file, so how big is the chance that there are a .PRG and a .D64 with identical names ?!?!*/
+                
+                    if(filename[lp] == 0)                     /*when the search string has not been ended but the searched filename has... no match*/
+                        break;                                /*we have no match*/
+                
+                    /*wildcard filter*/
+                    if (filename[lp] == '?')                /*when we encounter an '?', it does not matter what the real char of the filename is*/
+                        file->name_lfn[lp] = '?';            /*therefore we can replace the real char by a '?' so that the comparison (at the end of this loop) can still be valid*/
+            
+                    if (filename[lp] == '*')                /*when we have come so far and detected a * in our search string... we may consider this a match*/
+                        return(index);                            /*we have a partial or possible 100% match... but good enough to return with TRUE*/
+                }
+                while(file->name_lfn[lp] == filename[lp]);    /*do the compare of current char of both strings*/
+            }
+        }
+        if (!FileSearch(file, 1))                    /*search for the next file on the card. Attention: screws up secbuf!!*/
+            break;
+    }
+    return(FALSE);
+}
+
+/*this routine will load the file indicated by the given struct*/
+void LoadFileFromCard(struct file2TYPE *file)
+{
+    unsigned char    bytecount;
+    unsigned int    lp, blocksrem, filesizeinblocks;
+    unsigned long    remainingbytecounter;
+
+    SetErrorCode(0,LED_ON);                    /*unless we fail we will exit with no error*/
+    EOI = FALSE;
+    IEC_turnaround();                        /*we now SEND data to the bus so... make our device a talker*/
+    remainingbytecounter = file->size;
+    lp = 0;
+    bytecount = 0;
+
+    /*calculate the blocksize of this file*/
+    blocksrem = remainingbytecounter / 254;
+    filesizeinblocks = blocksrem;
+    if ((remainingbytecounter % 254) > 0)
+        blocksrem++;
+    blocksrem--;                    /*decrement by one, otherwise the countdown will stop at 1, and it must (offcourse) stop at 0*/
+    
+    FileReadSector(file);            /*read the first sector from the card (this is NOT a D64 sector) and contains MORE then 256 bytes*/
+    while(remainingbytecounter != 0)
+    {
+        if (bytecount == 0)
+            SetErrorCode(0,LED_ON);            /*turn LED on, to create a small blink at every block*/
+        if (bytecount == Blink_block)
+            SetErrorCode(0,LED_OFF);        /*turn LED off, to create a small blink at every block*/
+
+        if (remainingbytecounter == 1)        /*check for last byte*/
+        {
+            EOI = TRUE;                        /*indicate the last byte*/
+        }
+
+        IEC_send(block_buffer[lp]);
+        remainingbytecounter--;
+        bytecount++;
+        lp++;
+
+        if (lp == 512)
+        {
+            FileNextSector(file);        /*we must set file pointer to the next sector before we can read the next sector*/
+            FileReadSector(file);        /*its time to read another sector*/
+            lp = 0;
+        }
+
+        if (bytecount == 254)
+        {
+            blocksrem--;                                        /*another block has been send... update counter*/
+            print_D64_TSB(0, 0, blocksrem, filesizeinblocks);    /*print track, sector and remaining blocks*/
+            bytecount = 0;
+        }
+    }
+
+    IEC_undoturnaround();            /*were done talking towards the bus*/
+    SetErrorCode(0, LED_OFF);        /*all is OK, set the LED blinking mode to 'RITHM' to indicate that we have done somthing on a higher level then something within a D64-file*/
+}
+
+void LoadD64File(unsigned char trk, unsigned char sec, unsigned int filesizeinblocks)
+{
+    unsigned char lp;
+    unsigned int blocksrem;
+    unsigned char lasttrack, lastsector;
+
+    blocksrem = filesizeinblocks;
+    EOI = FALSE;
+    IEC_turnaround();                        /*we now SEND data to the bus so... make our device a talker*/
+
+    while(1)
+    {
+        SetErrorCode(0,LED_ON);                                    /*unless we fail we will exit with no error*/
+        print_D64_TSB(trk, sec, blocksrem, filesizeinblocks);    /*print track, sector and remaining blocks*/
+        lasttrack = trk;                                        /*keep extra buffer to remember what the last track was*/
+        lastsector = sec;                                        /*keep extra buffer to remember what the last sector was*/
+        D64LoadFile_X_Bytes(&file,trk,sec,0,256);                /*location of block to load and its size in bytes*/        
+        trk = block_buffer[0];                                    /*track position of the next block*/
+        sec = block_buffer[1];                                    /*sector position of the next block*/
+        blocksrem--;                                            /*decrement remaining blocks counter*/
+
+        if (trk != 0)                                            /*check on last block*/
+        {
+            for(lp=2;lp!=0;lp++)
+            {
+                    IEC_send(block_buffer[lp]);                    /*transmit the 254 bytes within this block to the listener*/
+                    if (lp == Blink_block)
+                        SetErrorCode(0,LED_OFF);                /*turn LED off, to create a small blink at every block*/
+            }
+        }
+        else                                                    /*transmission of data of the last block*/
+        {
+            print_D64_TSB(lasttrack, lastsector, blocksrem, filesizeinblocks);        /*print track, sector of the last block*/
+            for(lp=2;lp<(sec);lp++)                            /*transfer the remainder of the loaded last block*/
+                IEC_send(block_buffer[lp]);
+            break;
+        }
+    }
+    EOI = TRUE;                                /*indicate the last byte*/
+    IEC_send(block_buffer[sec]);                /*the position of the last byte is indicated by the value in register 'Sector'*/
+    IEC_undoturnaround();                    /*were done talking towards the bus*/
+    SetErrorCode(0,LED_OFF);                /*all is OK*/
+}
+
+/*Save the file to the D64, this requires the complete DOS handling !!!, since the CBM does not send*/ 
+/*the filesize, the exact filesize is only known when the file has allready been written. This is too*/ 
+/*late to update the progressbar on the LCD, so that's why this bar does not behave as expected*/
+unsigned char SaveD64File(void)
+{
+    unsigned char lp, fbpt, firsttrack, firstsector, bytecounter;
+    unsigned char track, sector, nexttrack, nextsector;
+    unsigned int blocksize;
+
+    blocksize = 0;
+
+    /*search for the first block location of the file to be saved*/
+    if (!D64SeekFreeBlock(&track, &sector))
+    {
+        SetErrorCode(72,LED_ERROR);                            /*error: disk or directory full*/
+        return(FALSE);
+    }
+
+    firsttrack = track;
+    firstsector = sector;
+    nexttrack = track;                                        /*update the track variable*/
+    nextsector = sector;                                    /*update the track variable*/
+    EOI = 0;
+    while(EOI == 0)
+    {
+        blocksize++;                                        /*increment blocksize counter*/
+        track = nexttrack;                                    /*update the track variable*/
+        sector = nextsector;                                /*update the track variable*/
+        if (!D64BlockAllocate(track, sector))                /*claim the next block, update the BAM*/
+        {
+            SetErrorCode(71,LED_ERROR);                        /*error: BAM is corrupt a flag has allready been cleared*/        
+            return(FALSE);                                    /*somebody or somthing has been messing with the BAM*/
+        }
+        fbpt = D64ReadFreeBlocksPerTrack(track) - 1;        /*decrement counter*/
+        D64WriteFreeBlocksPerTrack(track, fbpt);             /*save new value to BAM*/
+        if (!D64SeekFreeBlock(&nexttrack, &nextsector))        /*search for the next block location of the file to be saved*/
+        {
+            SetErrorCode(72,LED_ERROR);                        /*error: disk or directory full*/
+            return(FALSE);
+        }
+        /*the first two bytes of each block consist the 'track' and 'sector' of the next block*/
+        RAM_buffer[0] =    nexttrack;                            /*track of next block*/
+        RAM_buffer[1] = nextsector;                            /*sector of next block*/
+    
+        /*collect enough bytes to fill a block*/
+        bytecounter = 2;                                    /*byte counter to keep track of the position of the last byte within the file, since the first 2 bytes of the block are allways filled with non-data, we must add an offset of 2*/
+        for(lp=2;lp!=0;lp++)
+        {
+            SetErrorCode(0,LED_ON);                            /*unless we fail we will exit with no error*/
+            RAM_buffer[lp] = IEC_receive(TRUE);                /*receive a byte and acknowledge with a frame handshake*/
+            bytecounter++;
+// OutputToRS232();                    /*set standard output to RS232*/
+// printf(",%02x", RAM_buffer[lp]);    /*dump all received bytes to serial port*/
+// OutputToLCD();                        /*set standard output to LCD*/
+            if (EOI == 1)
+            {
+                RAM_buffer[0] =    0;                            /*there is no next block so the track value is an impossible one*/
+                RAM_buffer[1] = bytecounter;                /*there is no next block so the sector value is the position of the last byte*/    
+                do                                
+                {
+                    RAM_buffer[bytecounter] = 0x00;            /*fill the remaining area with 0x00*/
+                    bytecounter++;
+                }
+                while(bytecounter!=0);
+                break;
+            }
+
+            if (lp == Blink_block)
+                SetErrorCode(0,LED_OFF);                    /*turn LED off, to create a small blink at every block*/
+        }
+    
+        print_D64_TSB(track, sector, 0,blocksize);            /*print track, sector, remaining blocks and total number of blocks*/
+        D64BlockWrite(track, sector);                        /*write the block to D64*/
+    }
+
+    /*write the filename to the directory*/
+    if (!D64AddDirEntry(0x82,firsttrack,firstsector,command_string,blocksize,0,0,0,0,0))
+    {
+        SetErrorCode(72,LED_ERROR);                            /*error: disk or directory full*/
+        print_D64_TSB(track, sector, blocksize, blocksize);    /*print track, sector and remaining blocks and a fully filled bar*/
+        return(FALSE);
+    }
+
+    SetErrorCode(0,LED_OFF);                                /*all is OK*/
+    print_D64_TSB(track, sector, 0, blocksize);                /*print track, sector, remaining blocks creating a fully filled bar*/
+    return(TRUE);
+}
+
+/*Copy a file within the D64, this requires the complete DOS handling !!!*/ 
+/*the filename is stored in command_string*/
+unsigned char CopyD64File(unsigned char trk, unsigned char sec, unsigned int filesizeinblocks)
+{
+    unsigned int blocksrem;
+    unsigned char fbpt, track, sector, nexttrack, nextsector;
+
+    blocksrem = filesizeinblocks;
+    SetErrorCode(0,LED_ON);                    /*unless we fail we will exit with no error*/
+
+    /*search for the first block location of the new file to be saved*/
+    if (!D64SeekFreeBlock(&track, &sector))
+    {
+        SetErrorCode(72,LED_ERROR);                            /*error: disk or directory full*/
+        return(FALSE);
+    }
+
+    /*check if there is enough room free on the disk for the required copy*/
+    if (filesizeinblocks > D64LoadFreeBlocks())        /*read the number of free blocks from the D64 file*/
+    {
+        SetErrorCode(72,LED_ERROR);                            /*error: disk or directory full*/
+        return(FALSE);
+    }
+
+    /*write the filename to the directory, we can do that since we know the size of the file (ehhh. that's if it is written correctly*/
+    /*but we may asume that this is the case for normal disk use. This saves us a lot of checkking. And creates a more readable code */
+    D64AddDirEntry(0x82,track,sector,filename_string,filesizeinblocks,0,0,0,0,0);
+
+    while(blocksrem--)
+    {
+        if (!D64BlockAllocate(track, sector))                /*claim the next block, update the BAM*/
+        {
+            SetErrorCode(71,LED_ERROR);                        /*error: BAM is corrupt a flag has allready been cleared*/        
+            return(FALSE);                                    /*somebody or somthing has been messing with the BAM*/
+        }
+        fbpt = D64ReadFreeBlocksPerTrack(track) - 1;        /*decrement counter*/
+        D64WriteFreeBlocksPerTrack(track, fbpt);             /*save new value to BAM*/
+
+        /*search for the first block location of the new file to be saved*/
+        if (!D64SeekFreeBlock(&nexttrack, &nextsector))
+        {
+            SetErrorCode(72,LED_ERROR);                            /*error: disk or directory full*/
+            return(FALSE);
+        }
+        print_D64_TSB(trk, sec, blocksrem, filesizeinblocks);    /*print track, sector and remaining blocks*/
+        D64BlockRead(trk,sec);                                    /*this routine reads a block of a req. track-sector of a D64 into the RAM_buffer*/
+        trk = RAM_buffer[0];                                    /*the next track to be read*/
+        sec = RAM_buffer[1];                                    /*the next sector within that track*/
+        RAM_buffer[0] =    nexttrack;                                /*track of next block*/
+        RAM_buffer[1] = nextsector;                                /*sector of next block*/    
+        D64BlockWrite(track, sector);                            /*this routine write the contents of the RAM_buffer to the req. track-sector of the D64 file*/
+
+        track = nexttrack;                                        /*for the next block, set the correct next track and sector*/
+        sector = nextsector;
+    }
+    
+    /*write last block of the file*/
+    print_D64_TSB(trk, sec, blocksrem, filesizeinblocks);        /*print track, sector and remaining blocks*/
+    D64BlockRead(trk,sec);                                        /*this routine reads a block of a req. track-sector of a D64 into the RAM_buffer*/
+    D64BlockWrite(track, sector);                                /*this routine write the contents of the RAM_buffer to the req. track-sector of the D64 file*/
+    SetErrorCode(0,LED_OFF);                                    /*all is OK*/
+    return(TRUE);
+}
+
+
+/*this routine clears the entire block_buffer*/
+void Clear_block_buffer(void)
+{
+    unsigned int lp;
+
+    lp=0;
+    do
+    {
+        block_buffer[lp] = 0x00;
+        lp++;
+    }
+    while(lp<512);
+}
+    
+/*this routine formats the currently selected D64 image so it can be used to save your programs/data to*/
+/*the abillity not being able to create a new file saves us the effort of implementing a lot of FAT related actions*/
+/*Attention: this command does not implement the user options (disk label,disk ID). This command is for firmware & media testing purposes only*/
+void FormatD64File(unsigned char *diskname, unsigned char *diskid)
+{    /* '*filename' is actually the complete command_string as given by the user, this referencename is misleading and needs to be changed*/
+
+    unsigned int block_counter=0;
+    unsigned char lp,lp2,tr,se;
+
+    SetErrorCode(0,LED_ON);         /*unless we fail we will exit with no error*/
+    print_D64_TSB(0,0,(341-block_counter),341);
+
+    /*fill track 1 upto and including track 17 (all 21) sectors with 0x00*/
+    /*each MMC/SD-card block = 512 bytes, each D64 block = 256 bytes     */
+    /*17 tracks * 21 sectors = 357 D64 blocks or 178.5 MMC/SD-card blocks*/
+    Clear_block_buffer();                            /*clear the block_buffer*/
+    do
+    {
+        D64ConvertBlockToTrackSector((block_counter<<1), &tr, &se);
+        print_D64_TSB(tr,se,(341-block_counter),341);
+        FileWriteSector_X(&file, block_counter);    
+        block_counter++;
+    }
+    while(block_counter < 178);
+
+    block_buffer[256+0] = 18;    /*track of next block*/
+    block_buffer[256+1] = 18;    /*sector of next block*/
+    block_buffer[256+2] = 65;
+    block_buffer[256+3] =  0;
+    block_buffer[256+4] = 0x15; /*number of sectors within track-1*/
+    block_buffer[256+5] = 0xff;
+    block_buffer[256+6] = 0xff;
+    block_buffer[256+7] = 0x1f;
+    block_buffer[256+8] = 0x15; /*number of sectors within track-2*/
+    block_buffer[256+9] = 0xff;
+    block_buffer[256+10] = 0xff;
+    block_buffer[256+11] = 0x1f;
+    block_buffer[256+12] = 0x15; /*number of sectors within track-3*/
+    block_buffer[256+13] = 0xff;
+    block_buffer[256+14] = 0xff;
+    block_buffer[256+15] = 0x1f;
+    block_buffer[256+16] = 0x15; /*number of sectors within track-4*/
+    block_buffer[256+17] = 0xff;
+    block_buffer[256+18] = 0xff;
+    block_buffer[256+19] = 0x1f;
+    block_buffer[256+20] = 0x15; /*number of sectors within track-5*/
+    block_buffer[256+21] = 0xff;
+    block_buffer[256+22] = 0xff;
+    block_buffer[256+23] = 0x1f;
+    block_buffer[256+24] = 0x15; /*number of sectors within track-6*/
+    block_buffer[256+25] = 0xff;
+    block_buffer[256+26] = 0xff;
+    block_buffer[256+27] = 0x1f;
+    block_buffer[256+28] = 0x15; /*number of sectors within track-7*/
+    block_buffer[256+29] = 0xff;
+    block_buffer[256+30] = 0xff;
+    block_buffer[256+31] = 0x1f;
+    block_buffer[256+32] = 0x15; /*number of sectors within track-8*/
+    block_buffer[256+33] = 0xff;
+    block_buffer[256+34] = 0xff;
+    block_buffer[256+35] = 0x1f;
+    block_buffer[256+36] = 0x15; /*number of sectors within track-9*/
+    block_buffer[256+37] = 0xff;
+    block_buffer[256+38] = 0xff;
+    block_buffer[256+39] = 0x1f;
+    block_buffer[256+40] = 0x15; /*number of sectors within track-10*/
+    block_buffer[256+41] = 0xff;
+    block_buffer[256+42] = 0xff;
+    block_buffer[256+43] = 0x1f;
+    block_buffer[256+44] = 0x15; /*number of sectors within track-11*/
+    block_buffer[256+45] = 0xff;
+    block_buffer[256+46] = 0xff;
+    block_buffer[256+47] = 0x1f;
+    block_buffer[256+48] = 0x15; /*number of sectors within track-12*/
+    block_buffer[256+49] = 0xff;
+    block_buffer[256+50] = 0xff;
+    block_buffer[256+51] = 0x1f;
+    block_buffer[256+52] = 0x15; /*number of sectors within track-13*/
+    block_buffer[256+53] = 0xff;
+    block_buffer[256+54] = 0xff;
+    block_buffer[256+55] = 0x1f;
+    block_buffer[256+56] = 0x15; /*number of sectors within track-14*/
+    block_buffer[256+57] = 0xff;
+    block_buffer[256+58] = 0xff;
+    block_buffer[256+59] = 0x1f;
+    block_buffer[256+60] = 0x15; /*number of sectors within track-15*/
+    block_buffer[256+61] = 0xff;
+    block_buffer[256+62] = 0xff;
+    block_buffer[256+63] = 0x1f;
+    block_buffer[256+64] = 0x15; /*number of sectors within track-16*/
+    block_buffer[256+65] = 0xff;
+    block_buffer[256+66] = 0xff;
+    block_buffer[256+67] = 0x1f;
+    block_buffer[256+68] = 0x15; /*number of sectors within track-17*/
+    block_buffer[256+69] = 0xff;
+    block_buffer[256+70] = 0xff;
+    block_buffer[256+71] = 0x1f;
+    block_buffer[256+72] = 0x11; /*number of sectors within track-18*/
+    block_buffer[256+73] = 0xfc;
+    block_buffer[256+74] = 0xff;
+    block_buffer[256+75] = 0x07;
+    block_buffer[256+76] = 0x13; /*number of sectors within track-19*/
+    block_buffer[256+77] = 0xff;
+    block_buffer[256+78] = 0xff;
+    block_buffer[256+79] = 0x07;
+    block_buffer[256+80] = 0x13; /*number of sectors within track-20*/
+    block_buffer[256+81] = 0xff;
+    block_buffer[256+82] = 0xff;
+    block_buffer[256+83] = 0x07;
+    block_buffer[256+84] = 0x13; /*number of sectors within track-21*/
+    block_buffer[256+85] = 0xff;
+    block_buffer[256+86] = 0xff;
+    block_buffer[256+87] = 0x07;
+    block_buffer[256+88] = 0x13; /*number of sectors within track-22*/
+    block_buffer[256+89] = 0xff;
+    block_buffer[256+90] = 0xff;
+    block_buffer[256+91] = 0x07;
+    block_buffer[256+92] = 0x13; /*number of sectors within track-23*/
+    block_buffer[256+93] = 0xff;
+    block_buffer[256+94] = 0xff;
+    block_buffer[256+95] = 0x07;
+    block_buffer[256+96] = 0x13; /*number of sectors within track-24*/
+    block_buffer[256+97] = 0xff;
+    block_buffer[256+98] = 0xff;
+    block_buffer[256+99] = 0x07;
+    block_buffer[256+100] = 0x12; /*number of sectors within track-25*/
+    block_buffer[256+101] = 0xff;
+    block_buffer[256+102] = 0xff;
+    block_buffer[256+103] = 0x03;
+    block_buffer[256+104] = 0x12; /*number of sectors within track-26*/
+    block_buffer[256+105] = 0xff;
+    block_buffer[256+106] = 0xff;
+    block_buffer[256+107] = 0x03;
+    block_buffer[256+108] = 0x12; /*number of sectors within track-27*/
+    block_buffer[256+109] = 0xff;
+    block_buffer[256+110] = 0xff;
+    block_buffer[256+111] = 0x03;
+    block_buffer[256+112] = 0x12; /*number of sectors within track-28*/
+    block_buffer[256+113] = 0xff;
+    block_buffer[256+114] = 0xff;
+    block_buffer[256+115] = 0x03;
+    block_buffer[256+116] = 0x12; /*number of sectors within track-29*/
+    block_buffer[256+117] = 0xff;
+    block_buffer[256+118] = 0xff;
+    block_buffer[256+119] = 0x03;
+    block_buffer[256+120] = 0x12; /*number of sectors within track-30*/
+    block_buffer[256+121] = 0xff;
+    block_buffer[256+122] = 0xff;
+    block_buffer[256+123] = 0x03;
+    block_buffer[256+124] = 0x11; /*number of sectors within track-31*/
+    block_buffer[256+125] = 0xff;
+    block_buffer[256+126] = 0xff;
+    block_buffer[256+127] = 0x01;
+    block_buffer[256+128] = 0x11; /*number of sectors within track-32*/
+    block_buffer[256+129] = 0xff;
+    block_buffer[256+130] = 0xff;
+    block_buffer[256+131] = 0x01;
+    block_buffer[256+132] = 0x11; /*number of sectors within track-33*/
+    block_buffer[256+133] = 0xff;
+    block_buffer[256+134] = 0xff;
+    block_buffer[256+135] = 0x01;
+    block_buffer[256+136] = 0x11; /*number of sectors within track-34*/
+    block_buffer[256+137] = 0xff;
+    block_buffer[256+138] = 0xff;
+    block_buffer[256+139] = 0x01;
+    block_buffer[256+140] = 0x11; /*number of sectors within track-35*/
+    block_buffer[256+141] = 0xff;
+    block_buffer[256+142] = 0xff;
+    block_buffer[256+143] = 0x01;
+
+    lp2=0;
+    lp=144;
+
+    while((lp<160) && (diskname[lp2] != 0))        /*diskname*/        
+    {                                            /*--------*/
+        block_buffer[256+lp] = diskname[lp2];    /*copy character*/
+        lp2++;
+        lp++;
+    }
+    while (lp<160)
+    {
+        block_buffer[256+lp] = 160;                /*fill unused locations with shifted spaces, default value*/
+        lp++;
+    }
+
+    block_buffer[256+160] = 160;
+    block_buffer[256+161] = 160;
+
+    if (diskid[0] == 0)                            /*disk-ID*/
+    {                                            /*-------*/
+        block_buffer[256+162] = '0';            /*default value*/
+        block_buffer[256+163] = '0';            /*default value*/
+    }
+    else
+    {
+        block_buffer[256+162] = diskid[0];        /*copy character*/
+        if (diskid[1] == 0)
+        {
+            block_buffer[256+163] = 160;        /*default value*/
+        }
+        else
+        {
+            block_buffer[256+163] = diskid[1];    /*copy character*/
+        }
+    }
+
+    block_buffer[256+164] = 160;    
+    block_buffer[256+165] = 50;    /*DOS VERSION*/
+    block_buffer[256+166] = 65;    /*DOS VERSION*/
+    block_buffer[256+167] = 160;
+    block_buffer[256+168] = 160;
+    block_buffer[256+169] = 160;
+    block_buffer[256+170] = 160;
+
+    lp = 171;
+    while (lp != 0)                /*fill remaining bytes from 171 up to and including 255 with 0x00*/
+    {
+        block_buffer[256+lp] = 0x00;
+        lp++;
+    }
+
+    D64ConvertBlockToTrackSector((block_counter<<1), &tr, &se);
+    print_D64_TSB(tr,se,(341-block_counter),341);
+    FileWriteSector_X(&file, block_counter);    
+    block_counter++;
+
+    /*fill remaining tracks 18-1 to 35-16 with 0x00                      */
+    /*each MMC/SD-card block = 512 bytes, each D64 block = 256 bytes     */
+    Clear_block_buffer();                            /*clear the block_buffer*/
+    do
+    {
+        D64ConvertBlockToTrackSector((block_counter<<1), &tr, &se);
+        print_D64_TSB(tr,se,(341-block_counter),341);
+        FileWriteSector_X(&file, block_counter);    
+        block_counter++;
+    }
+    while(block_counter < 342);
+    SetErrorCode(0,LED_OFF);
+}
+
+/*this routine is to be used to handle the errorcode and the LED-blink-mode in an easy way*/
+void SetErrorCode(unsigned char error, unsigned char LEDmode)
+{
+    /*the original 1541 used the LED to display the results of the power-on selftest*/
+    /* No Blink       Kernal (E000-FFFF) ROM or 6522 VIA Failure */
+    /* One Blink      6116 RAM Failure                           */
+    /* Two Blinks     Possible Zero Page RAM Failure             */
+    /* Three Blinks   DOS (C000-CFFF) ROM Failure                */
+    /* Four Blinks    DOS (C000-CFFF) ROM Failure                */
+    /* Five Blinks    6116 RAM Failure                           */
+    /* Six Blinks     6116 RAM Failure                           */
+    /* Seven Blinks   6116 RAM Failure                           */
+    /* Eight Blinks   6116 RAM Failure                           */
+    /*Note: at this moment the selftest (and it's blinking modes) is/are not supported (yet)*/
+
+    if ((error == 0) && (error_code == 73))    /*when there is no error-73 to maintain (ROM version), change to the new error_code*/
+    {
+        /*do not change the error_code, because there is no error and the code 73 must be preserved*/
+    }
+    else
+    {        
+        if (error != error_code)            /*only update the screen when the error_code has changed*/
+        {                                    /*because when there is no new info... there is no reason to print to the display what is allready there*/
+            error_code = error;        
+    //        Lcd_XY_address(2,4);            /*if there is any printing to the display to be done, it must be done on line...*/
+            printf("%02d",error_code);        /*show the error code*/
+        }
+
+    //    if ((error == 21) || (error == 62)) /*these error(s) create this sound (i.e. error 62 = file not found)*/
+    //        PlaySample_HeadBangRattle();    /*play sample that suits this error situation*/
+    }
+
+    switch(LEDmode)
+    {
+        case LED_OFF:
+        {
+  //          TMR0ON = 0;                    /*switch timer-0 OFF*/
+            LED_GREEN = 0;                /*switch LED-OFF*/
+            LED_RED = 0;                /*switch LED-OFF*/
+            break;
+        }
+
+        case LED_ON:
+        {
+//            TMR0ON = 0;                    /*switch timer-0 OFF*/
+            LED_GREEN = 1;                /*switch LED-ON*/
+            LED_RED = 0;                /*switch LED-ON*/
+            break;
+        }
+
+
+        case LED_ERROR:
+        {
+            Blink_mode = LED_ERROR;
+            LED_status = 0;                /*status of the LED (0=OFF)*/
+  //          TMR0H = 0xFF;                /*set registers to enter timer-o interrupt as quickly as possible*/
+  //          TMR0L = 0xFF;
+  //          TMR0ON = 1;                    /*switch timer-0 on*/
+            break;
+        }
+
+        default:
+        {
+   //         TMR0ON = 0;                    /*switch timer-0 OFF*/
+            LED_GREEN = 0;                /*switch LED-OFF*/
+            LED_RED = 0;                /*switch LED-OFF*/
+        }
+    }
+}
+
+void SendErrorMessage(void)
+{
+    EOI = FALSE;
+    LED_GREEN = 1;                            /*drive LED-ON*/
+    IEC_turnaround();                        /*we now SEND data to the bus so... make our device a talker*/
+    IEC_send_number_as_ASCII(error_code);    /*send error-code*/
+    IEC_send(0x2C);                            /*','*/
+
+    switch (error_code)
+    {
+        case 0:        /*OK (not an error*/
+        {
+            IEC_send_string("OK");
+            break;
+        }
+
+        case 1:        /*files scratched (not an error)*/
+        {
+            IEC_send_string("FILES SCRATCHED");
+            break;
+        }
+
+        case 2:;    /*Unused error message (should be ingnored)*/
+        case 3:;    /*Unused error message (should be ingnored)*/
+        case 4:;    /*Unused error message (should be ingnored)*/
+        case 5:;    /*Unused error message (should be ingnored)*/
+        case 6:;    /*Unused error message (should be ingnored)*/
+        case 7:;    /*Unused error message (should be ingnored)*/
+        case 8:;    /*Unused error message (should be ingnored)*/
+        case 9:;    /*Unused error message (should be ingnored)*/
+        case 10:;    /*Unused error message (should be ingnored)*/
+        case 11:;    /*Unused error message (should be ingnored)*/
+        case 12:;    /*Unused error message (should be ingnored)*/
+        case 13:;    /*Unused error message (should be ingnored)*/
+        case 14:;    /*Unused error message (should be ingnored)*/
+        case 15:;    /*Unused error message (should be ingnored)*/
+        case 16:;    /*Unused error message (should be ingnored)*/
+        case 17:;    /*Unused error message (should be ingnored)*/
+        case 18:;    /*Unused error message (should be ingnored)*/
+        case 19:    /*Unused error message (should be ingnored)*/
+        {
+            IEC_send_string("N/A");
+            break;
+        }
+
+        case 20:;    /*Header descriptor byte not found ($08) Each sector is preceeded by an 8-byte header block, which starts with the value $08. If this value is not $08, this error is generated*/
+        case 21:;    /*Each sector data block and header block are preceeded by SYNC marks. If *no* sync sequence is found, then the  whole track is unreadable, and likely unformatted.*/
+        case 22:;    /*Data descriptor byte not found ($07)        Each sector data block is preceeded by the value $07, the[]= "data block" descriptor. If this value is not there, this error is generated. Each encoded sector has actually 260 bytes. First is the descriptor byte, then follows the 256 bytes of data, a checksum, and two[]= "off" bytes.*/
+        case 23:;      /*Checksum error in data block                The checksum of the data read of the disk is calculated, and compared against the one stored at the end of the sector. If there's a discrepancy, this error is generated.*/
+        case 24:;    /*Write verify (on format)                    */
+        case 27:    /*Checksum error in header block            The 8-byte header block contains a checksum  value, calculated by XOR'ing the TRACK,  SECTOR, ID1 and ID2 values. If this checksum is wrong, this error is generated.*/
+        {
+            IEC_send_string("READ ERROR");    
+            break;
+        }
+
+        case 25:;     /*Write verify error                        Once the GCR-encoded sector is written out, the drive waits for the sector to come around again and verifies the whole 325-byte GCR block. Any errors encountered will generate this error.*/
+        case 28:    /*Write error                                In actual fact, this error never occurs, but it is included for completeness.*/
+        {
+            IEC_send_string("WRITE ERROR");    
+            break;
+        }
+
+        case 26:    /*Write protect on                            Self explanatory. Remove the write-protect tab, and try again.*/
+        {
+            IEC_send_string("WRITE PROTECT ON");    
+            break;
+        }
+
+        case 29:    /*Disk sector ID mismatch                    The ID's from the header block of the currently read sector are compared against the ones from the header of 18/0. If there is a mismatch, this error is generated.*/
+        {
+            IEC_send_string("DISK ID MISMATCH");    
+            break;
+        }
+
+        case 30:;    /*general syntax error*/
+        case 31:;    /*invalid command*/
+        case 32:;    /*long line*/                
+        case 33:;    /*invalid fileSelectedFileName*/
+        case 34:;    /*no file given*/
+        case 39:    /*command file not found*/
+        {
+            IEC_send_string("SYNTAX ERROR");    
+            break;
+        }
+
+        case 50:    /*record not present*/
+        {
+            IEC_send_string("RECORD NOT PRESENT");    
+            break;
+        }
+
+        case 51:    /*overflow in record*/
+        {
+            IEC_send_string("OVERFLOW IN RECORD");    
+            break;
+        }
+
+        case 52:    /*file too large*/
+        {
+            IEC_send_string("FILE TOO LARGE");    
+            break;
+        }
+
+        case 60:    /*File open for write*/
+        {
+            IEC_send_string("WRITE FILE OPEN");    
+            break;
+        }
+
+        case 61:    /*File not open*/
+        {
+            IEC_send_string("FILE NOT OPEN");    
+            break;
+        }
+
+        case 62:    /*File not found*/
+        {
+            IEC_send_string("FILE NOT FOUND");    
+            break;
+        }
+
+        case 63:    /*File exists*/
+        {
+            IEC_send_string("FILE EXISTS");    
+            break;
+        }
+
+        case 64:    /*File type mismatch*/
+        {
+            IEC_send_string("FILE TYPE MISMATCH");    
+            break;
+        }
+
+        case 65:    /*No block*/
+        {
+            IEC_send_string("NO BLOCK");    
+            break;
+        }
+
+        case 66:    /*Illegal track or sector*/
+        {
+            IEC_send_string("ILLEGAL TRACK AND SECTOR");
+            break;
+        }
+
+        case 67:    /*Illegal system track or sector*/
+        {
+            IEC_send_string("ILLEGAL SYSTEM T OR S");
+            break;
+        }
+
+        case 70:    /*No channels available*/
+        {
+            IEC_send_string("NO CHANNEL");
+            break;
+        }
+
+        case 71:    /*Directory error*/
+        {
+            IEC_send_string("DIRECTORY ERROR");
+            break;
+        }
+
+        case 72:    /*disk full or directory full*/
+        {
+            IEC_send_string("DISK FULL");
+            break;
+        }
+
+        case 73:    /*DOS mismatch / Powerup message/write attempt with DOS mismatch*/
+        {
+            IEC_send_string("V");
+            IEC_send_number_as_ASCII(RELEASE_VERSION);
+            IEC_send('-');
+            IEC_send_number_as_ASCII(RELEASE_VERSION_SUB);
+            IEC_send('-');
+            IEC_send_number_as_ASCII(RELEASE_VERSION_SUB_SUB);
+            break;
+        }
+
+        case 74:    /*no disk in drive or no device 1 (8050 only)*/
+        {
+            IEC_send_string("DRIVE NOT READY");
+            break;
+        }
+
+        default:
+        {
+            IEC_send_string("ERROR UNKNOWN");
+            break;
+        }
+    }
+
+    DelayBigMs(50);                                    /*some small delay to give the computer time to process the string*/
+    IEC_send(0x2C);                                    /*','*/
+    if (error_code == 1)                            /*check for the FILES SCRATCHED-error*/
+        IEC_send_number_as_ASCII(files_scratched);    /*last accessed track variable is replaced by the number of scratched files*/
+    else
+        IEC_send_number_as_ASCII(LastTrack);        /*last accessed track variable*/
+    IEC_send(0x2C);                                    /*','*/
+    IEC_send_number_as_ASCII(LastSector);            /*last accessed sector variable*/
+    EOI = TRUE;                                        /*indicate the last byte*/
+    IEC_send(0x0D);                                    /*CARRIAGE RETURN*/
+    IEC_undoturnaround();                            /*were done talking towards the bus*/
+    SetErrorCode(0,LED_OFF);                        /*error-code is 0, LED is OFF*/
+}
+/*****************************************************************************************************************/
+/*****************************************************************************************************************/
+/*****************************************************************************************************************/
+
+unsigned char ReadDeviceJumper(void)
+{
+    if (JUMPER_J2 == 0)                    /*check the device number jumper to see what the req. device number should be*/
+        return(8);
+    else 
+        return(9);
+}
+
+/*read the buttons using the ADC, the multiplexed buttons require only one IO-pin. The only thing is... only one button can be pressed/detected at the same time*/
+unsigned char ReadButtons(void)
+{
+ 
+        return(FALSE);                            /*the 1541-III DTV, does NOT support the use of buttons*/
+ 
+}
+
+
+/*
+There's no shame in writing comments in your sourcecode.
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.h	Mon Aug 22 05:48:51 2011 +0000
@@ -0,0 +1,44 @@
+#ifndef _MAIN_H_INCLUDED
+#define _MAIN_H_INCLUDED
+
+/*constants*/
+#define        MAX_NUMBER_OF_DOS_BUFFERS    5        /*the maximum numbers of available buffers within this device*/
+
+/*structures*/
+struct    DOS_buffer_struct
+{
+    unsigned char    buffer_in_use;                /*this flag indicates wether the buffer is allready in use*/            
+    unsigned char    buffer[256];                /*the buffer capable of holding a complete block*/
+};
+
+struct    DOS_channel_struct
+{
+    unsigned char    channel_in_use;                /*this flag indicates wether this channel is allready in use*/
+    unsigned char    next_action;                /*this holds the next action (if nothing interupts it) for this channel*/
+    unsigned char    filename[17];                /*the actual filename, as it is stored on the disk*/
+    unsigned char    filetype;                    /*filetype can be sequential, program, user, etc.*/
+    unsigned char    RW;                            /*file read or write*/
+    unsigned char    track;                        /*the current track position on the disk regarding this file*/
+    unsigned char    sector;                        /*the current sector position on the disk regarding this file*/
+    unsigned char    buffer_pointer;                /*the current byte position within the block specified by track and sector on the disk regarding this file*/
+    unsigned char    used_buffer;                /*this register holds the value of the connected buffer (if required)*/
+    unsigned char    status;                        /*the current status of this file entry in the sa_DOS_buffer*/
+};
+
+/*variables*/
+extern unsigned char    RAM_buffer[256];        /*this is the buffer capable of holding one 256 byte block, a memory area to which the user or the 1541-III can write/read data to/from*/
+//extern unsigned char    BAM_buffer[162];        /*this buffer holds the Block Allocation Map, required for when we want to write to the D64 (max 40 tracks)*/
+extern unsigned char     block_buffer[512];        /*this buffers the data 'as read from' or 'to be written to' the card*/
+extern struct            DOS_buffer_struct    DOS_buffer[MAX_NUMBER_OF_DOS_BUFFERS];    /*this array of structs holds the information about the currently used buffers*/
+extern struct            DOS_channel_struct    DOS_channel[16];    /*this array of structs holds this information about the currently used channels*/
+
+extern unsigned char Card_CID(void);
+extern unsigned char Card_CSD(void);
+
+/*routines*/
+/*--------*/
+// void delay_10uS(unsigned long delay);
+
+//void CLRWDT();
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Mon Aug 22 05:48:51 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/9114680c05da