Gert van der Knokke / C1541III

Description: C1541-III mbed edition

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.c Source File

main.c

00001 /*==================================================================================*/
00002 /*==   This software is designed to be compiled by the Hi-Tech PIC Ccompiler      ==*/
00003 /*==                                                                              ==*/
00004 /*==   Attention, make sure to compile with the following options selected:       ==*/
00005 /*==           printf: integer + long + float                                        ==*/
00006 /*==================================================================================*/
00007 /*  1541-III (simply said: a 1541 clone that uses MMC/SD-cards)                     */
00008 /*                                                                                  */
00009 /*                                  This is MAIN                                    */
00010 /*                                  ------------                                    */
00011 /*                                                                                  */
00012 /* This program is designed to control the 1541-III project:                        */
00013 /* The 1541-III project is a device to be connected to the IEC-bus of a C64         */
00014 /* The device will act as if it was a 1541 diskdrive. The diskimages are to be      */
00015 /* stored on a MMC or SD-card in the D64 file format (the most common emulator file */
00016 /* for C64 disk images. By selecting a specific D64 file on the card you select the */
00017 /* diskimage to be seen by the connected C64. By mimmicing a 1541 drive the C64 does*/
00018 /* not require any extra software while keeping the flexability of a modern medium. */
00019 /* This way the huge amount of software on the WEB becomes available on your stock  */
00020 /* C64, like the good old days, checking out your new 'disks' full with hours of fun*/
00021 /*                                                                                  */
00022 /* Note:                                                                            */
00023 /* a sector on a 5,25" disk has the size of 256 bytes, this is also called a block  */
00024 /*                                                                                  */
00025 /*      ATTENTION: all settings are calculated for a crystal freq. of 20MHz         */
00026 /*                                                                                  */
00027 /*----------------------------------------------------------------------------------*/
00028 
00029 #define            RELEASE_VERSION            8    /*last 2 digits of Year    */
00030 #define            RELEASE_VERSION_SUB        2    /*Month                    */
00031 #define            RELEASE_VERSION_SUB_SUB    27    /*Day                    */
00032 
00033 /*  History:
00034     --------
00035 
00036     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)
00037     (this information was supplied by: Dirk (a.k.a. SKERN, from www.dienstagstreff.de)
00038 
00039     debug datahandler!!!
00040     2011-08-22  First version of this software ported to mbed by Gert van der Knokke
00041     2008-02-27    release date of this wonderfull version
00042     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.
00043     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)
00044                 The routine ImageDirectory is renamed to D64Directory simply because the D64 directory routine cannot easily be transformed into something universal
00045     2008-02-15    added a default value to error_code declaration
00046                 made the separation line in the card-directory a bit nicer and added an extra check that removed the undesired first seperator line
00047     2008-02-14    changed the serial debugging output to some nice ASCII/art looking debugging output (filling some spare minutes)
00048                 did some T64-file preparations...
00049     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
00050                 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...
00051                 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
00052     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.
00053     2008-02-10    removed write protect check as it does not have any value and can be very anoying
00054                 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)
00055     2008-02-08    fixed the problem in FAT.c (filesearch) regarding the backwards searching within subdirectories.
00056                 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>
00057     2008-02-05    tested the VIC20 mode on a real vic20, and as expected, there where still too much chars on one line, fixed
00058     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.
00059     2008-02-01    improved (fat.c) filesearch routine for subdirectory support, it appears to work
00060     2008-01-31    testing of subdirs
00061     2008-01-25    added some extra output on the LCD contrast setting, when a user presses a button it shows on the serial port
00062     2008-01-15    countfiles now show the user that it is counting files (message to display)
00063                 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)
00064     2008-01-12    fixed problem with root selection when using buttons (these routines required changes due to the added subdir functionality)
00065                 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,
00066                 so this is now changed to sort of slider, like you may know from "modern" operating systems like Windows
00067                 Seekfileoncard return the file index (again)
00068                 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
00069                 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)
00070                 Added the suggestions made by jussi, to the LCD routines for better LCD clone compatibillity
00071     2008-01-11    restoring of the button functions, these functions required changes due to the added subdir functionality
00072     2008-01-10    added countfiles routine (counting files can be usefull after all)
00073     2008-01-08    Playing with subdirs (part...+2)
00074                 nu is er de uitzondering Root (index 0) maar eigenlijk is dit geen uitzondering.
00075                 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
00076     2008-01-07    Playing with subdirs (part...+1)
00077     2008-01-05    Playing with subdirs (part...)
00078     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
00079     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)
00080     2008-01-02    removal of code that uses index number to refer to files
00081                 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
00082     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
00083                 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)
00084                 Sorting on alfabetical order is not going to happen as it would take too much memory or would be too time consuming
00085     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?!?!
00086     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)
00087                 when used in VIC-20 mode the directory width is limitted to 20 characters, so it displays nicely on a VIC-20
00088                 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
00089                 Every entry that needs to be loaded as a directory now is display with a proceeding $-sign.
00090                 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.
00091                 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
00092                 it saves the user the trouble of inserting the $-sign in the directory entry when he/she wants to load it.
00093                 Changed the search routine "SeekFileOnCard" in order to work with the longer filenames and to accept filenames without extensions
00094     2007-12-21    worked on directory formatting (making sure that it looks OK after LOAD"$")
00095                 also created 2 different directory looks. A small look for the VIC20 and a normal look for others.
00096                 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)
00097                 Simply use the standard UI- and UI+ commands to toggle between normal and VIC20 mode (see manual)
00098     2007-12-20    worked on longfilenames
00099     2007-12-19    now that longfilenames profe to be functional, let's apply them in the carddirecory routine(s)
00100     2007-12-18    experimenting with FAT extra's (playing with longfilenames)
00101     2007-10-27    a small change in LCD_nokia_3310.c (see it's history) solved the inverted character problem, now lines of inverted
00102                 char look beter and the contrast is not disturbed. I expect that this would solve other contrast problem as well,
00103                 there are people out there with LCD's that for some reason have a very "light" contrast and are difficult to read when
00104                 the display's content changes rapidly, it must be something likes this.
00105     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
00106     2007-10-24    added the 1541-III dtv C64 edition to the list of recognized devices
00107     2007-10-18    added the 1541-III second batch to the list of recognized devices
00108     2007-10-17    added some extra features for hardware testing
00109                 when no card is inserted and the user pushes the i-button then the hardwaretestmenu is entered
00110     2007-10-11    used the enum statement for the first time, it simplifies constant coding... a little
00111     2007-08-15    still lot's of work to be done, but this version is suitable for beta-release... so release it!
00112                 people have been waiting long enough for a more stable release... so give it to them although it's not 100%
00113                 it IS better then the previous versions.
00114     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)
00115                 during button selection the progress-bar indicates where we are in the directory
00116                 during button selection some additional file information is shown on the third line
00117     2007-06-28    small changes in display layout, moved index to error-line
00118     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
00119                 display line-2 now shows the last error code (if not 0 or 73 (directly after reset))
00120                 the filename that is being loaded or saved is not displayed to the display any more (only visible via serial port)
00121     2007-06-25    added the sound samples made by Willem K.(Thanks a lot Willem for your excellent work, unfortunatley the
00122                 hardware does not allow it to play the samples to it's full quality, but the sounds are still very
00123                 distinctive and recognisable as 1541 drive sounds)
00124     2007-05-17    added a clear display line after the execution of LOAD, SAVE etc.
00125     2007-05-15    the last few days have been spend with typing old listings from books to further test the current firmware
00126     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
00127                 set the delay to 1000uSec, no problems any more.
00128     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)
00129     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)
00130                 the new location of this delay ensure a quicker response time when waiting for a command
00131     2007-04-24    stared at the code tried to analyze what went wrong, failed to solve it
00132     2007-04-23    IECUNDOTURNAROUND should not check on clock, corrected in IEC_bus.C
00133     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.
00134                 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...
00135     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
00136     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!
00137                 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!
00138     ----------    Vacation @ Lommersbergen
00139     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)
00140                 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!
00141     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
00142             |    the LED RITHM blinking routines interfere with the IEC timing! DAMN! (those blinking routines I liked the most)
00143              ->    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...
00144     2007-04-07    - Bugfix in FAT.C reported and fixed by Mattias Olsson
00145                 - 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
00146                   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
00147     2007-04-05    added the function to readout the result of the opened buffer (GET#1, A$ directly after OPEN 1,8,2,"#")
00148     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,
00149                 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
00150                 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
00151                 out the hard way (offcourse))
00152     2007-04-02    worked on the same 'problem' again
00153     2007-04-01    continue of the prev. day
00154                 the check IEC_CLOCK == 1 in UNDOTURNAROUND now has a time-out, simply to improve reliablillity... it helps a lot!
00155                 separated B-R and U1, since the first is 254 bytes and the second if the full 256 byte block-read
00156                 separated B-W and U2, since the first is 254 bytes and the second if the full 256 byte block-write
00157     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)
00158                 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...
00159     2007-03-30    worked on the U1 and U2 command
00160                 added a buffer pointer to the D64blockread function and named this function D64blockread_new
00161                 added a buffer pointer to the D64blockwrite function and named this function D64blockwrite_new
00162                 replaced the code located under "errochannelhandler" under the openhandler (where it belongs)
00163     2007-03-29    worked on the U1 and U2 command, these commands are handled in an identical way as the B-P command
00164     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,
00165                 although the mean the same, it is very confusing to say the least. But it becomes more and more clearer everyday...)
00166                 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.
00167                 Also this routine returns the input string with a pointer to the last location (so you know where to find the second number etc.)
00168     2007-03-27    worked on the open command and the b-p command
00169     2007-03-26    created the DOS_buffer and DOS_channel structures to hold all the required information
00170     2007-03-25    complete rework on the open command and on the buffer definitions... I was wrong all along (damn...)
00171                 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
00172                 replaced the variable Dos_buffer.status to NextAction in order to keep track of the next action of this device
00173     2007-03-23    added more comments and worked on the openhandler (made some small progress, but lots of work to be done)
00174     2007-03-22    added extra comments (over serial) for easier debugging of new code
00175     2007-03-20    just staring at the code...
00176     2007-03-18    worked on the channel handling, lots of work to do... but very important so it must be done,
00177                 but it takes a lot of time before i will get it right, it's very confusing to implement (although
00178                 the concept is very clear and logical, the low level handling makes it complex and therefore
00179                 confusing if not written down correctly the first time
00180     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)
00181                 added filter on ATN-line, to prevent possible glitches from false triggering the ATN-interrupt
00182     2007-03-12    Created the color cycle routine
00183                 Created a small blink at every transmitted/received block
00184                 The LED fade on and fade off function is discarded because it function as expected.
00185                 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,
00186                 you might miss an important event, it creates additional loading delays which are anoying with small files etc.)
00187     2007-03-08    LED fade-on/off function, the LED does not go on and off its fades gently to the required state
00188     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
00189     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
00190     2007-01-30    ...
00191     2007-01-25    started with the coding of the following commands: B-P:, U1: and U2:
00192     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
00193     2006-12-06    release date of firmware version
00194     2006-11-21    reworked improvement... now also the disk-ID is used (if given by user)
00195                 simplified the splitstring on comma, column and equal into one routine: splitstringon_sign, where the sign to 'split on' must be given
00196     2006-11-20    improved formatting routine, now the diskname is actually used (if given by user)
00197     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)
00198                 BUG:direct loading of a prg file from root does not seem to work any more !?!?! thought it was fixed
00199                 Fixed: caused by checking for FILE_PRESENT, which should be !=FALSE, because the new routine have more output then TRUE or FALSE
00200     2006-11-13    Added contrast setting under iec command control: open15,device,15,"LCDCONTRAST=ddd";close15
00201     2006-11-12    Implemented the copy function, there was allready a beginning for several weeks, but never really implemented until now.
00202     2006-11-11    Sint Maarten, dus de bel gaat vaak...
00203                 Finished the routines and testing of the D64 file selection (directory loading) by name entry
00204                 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)
00205                 Setting of device ID using software is functional
00206     2006-11-09    started with the D64 file selection by name (user request, because currently it is D64 file selection by index only)
00207     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.
00208                 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
00209                 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.
00210     2006-11-07    added some extra checkpoints for card removal, there were some situations where the user could bypass the card removal checking routines,
00211                 causing unexpected behavior. This is now fixed.
00212     2006-11-06    did some testing on the load with and without card inserted
00213     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
00214                 BUGFIX: the FREEIEC routine in combination with the disabling of the ATN-based interrupt solved the problem
00215     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
00216                 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.)
00217                 User request: added an extra space so that when more then 99files are stored on the card, the directory is still nicely aligned
00218                 BUG:loading of .PRG files does not seem to work when the whole filename is entered,
00219                 but it does work when a part of the filename followed by a * is entered... curious, but true?
00220                 BUGFIX: the CBM computers do not recognize the '~'-sign and when printed to screen
00221                 they show a pi-sign. Unfortunately, this sign cannot be entered during load/save.
00222                 so when doing this a 0xff value is substituted. Very unfortunate because this means
00223                 the comparison for the filenamesearch fails. By replacing the '~'-sign by the '/'-sign
00224                 these problems are simply avoided and all works as intended.
00225     2006-11-02    ALL routines are functional again, hurray for me, wahoo!!!
00226     2006-11-02    making all 1541-III functions functional again as it was intended. So that you can use
00227                 OPEN 15,9,15,"S:blabla"
00228                 as well as:
00229                 OPEN 15,9,15
00230                 PRINT#15,"S:blabla"
00231     2006-11-01    1541-III is functional again HURRAY !!!
00232                 New statemachine functions, the big difference between the new staemachine and the old one is basiccally that the old statemachine
00233                 executed the open command BEFORE the UNLISTEN command, while the new statemachine executes the OPEN command AFTER the UNLISTEN
00234                 command, this is a big difference, suddenly some mysterious delays that could not been found in the specs are not required any
00235                 more. Suddenly it becomes clear that the strange delays were not neccessary after all as long as the proper statemachine was used.
00236     2006-10-31    statemachine is better but not funcional yet... getting there
00237     2006-10-30    fucked up the statemachine pretty bad... but it's the only way to build something better. Start with rebuilding it
00238                 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)
00239     2006-10-25    placed the LOAD routines in channel-0 (thats the location where these routine belong in the real 1541)
00240                 placed the SAVE routines in channel-0 (thats the location where these routine belong in the real 1541)
00241                 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
00242     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
00243                 load and save routines are only avaiable under channel 0 and 1
00244     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)
00245                 because of this it was possible to use the command :
00246                 OPEN 15,9,15,"N:blabla"
00247                 but not the command:
00248                 OPEN 15,9,15
00249                 PRINT#15,"N:blabla"
00250                 this is now fixed (both commands work) since the errorchannel is not only used for the handling of the errormessages
00251     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.)
00252                 .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
00253                 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
00254                 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)
00255     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-)
00256     2006-10-16    replaced the '.' in the errorcode 73 for '-' which should be better regarding readabillity
00257     2006-10-15    shortened the default errorcode by nine characters (removed 1541-III<space>), it now only shows the versionnumber of the software
00258                 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.
00259     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...
00260     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
00261     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)
00262                 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.
00263     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...
00264     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>)
00265                 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
00266     2006-09-12    REPLACE-command (combination of SCRATCH and SAVE), tested it and it works, commando does not work with it ?!?!? further testing required
00267     2006-09-11    RENAME-command is functional
00268                 scratch command now includes the correct error handling, the error-code 1 shows the number of files scratched in the last track value
00269     2006-09-10    scratch function nows also includes the use of wildcards (identical to file-loading wildcards)
00270                 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
00271     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.
00272     2006-09-04    a small step further with write support
00273     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
00274     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
00275                 also now all large buffers are defined in main.c (cause there is where you want to keep an overview of your resources
00276     2006-08-31    moved all low level D64 acces routines to: D64_decoder.c
00277     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)
00278                 created the BLOCK-READ routine, which is even easier then BLOCK-WRITE
00279                 created the BLOCK-ALLOCATE routine,...
00280                 created the BLOCK-FREE routine,...
00281                 The actual command using the above routines still has to be written... (so much to do in so little time)
00282     2006-08-28    added the testing function 'n:' this function tests the block write to card routine
00283                 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!!!
00284     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
00285                 improved filefilter routines and combined them into one single routine, this makes the software easier to maintain
00286                 simplified some areas of the code thanks to the Lcd_CharBold() function, saves a lot of putch(...)
00287     2006-08-21    added more debugging info in order to find the problem regarding the problems with some card not being supported...
00288     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))
00289     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
00290     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
00291                 contrast can only be changed when no card is inserted !!!
00292     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.
00293     2006-07-09    changed the read file statemachine, now the read is combined with write, since the command sequence is allmost identical
00294                 corrected the file-locked indicator (it was printed BEFORE the filetype while it should be printed AFTER... silly me)
00295                 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
00296                 added an extra print track and sector routine to properly display the last track and sector of the loaded file
00297                 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!
00298                 removed stupid, stupid, stupid little BUG which prevented the second-last byte from being transferred during load, causing some files to fail after loading
00299     2006-07-05    improved start-up behaviour, now the 1541-III does not 'hang-up' when accessed without card (basically removal of some busyloops
00300                 added textual message 'LOADING' to the loading related actions (SAVING, DELETING etc. is offcourse to be expected)
00301     2006-07-04    changed release version number into release version data (thats easier to track changes in the history, you never know...)
00302     2006-07-03    buttons, functions great, you cannot select a non D64 file
00303                 detection of card removal during operation
00304     2006-07-02    added functional button selection, but it functions only once?!?!
00305                 added a simple retry mechanism in 'Init_Card_SPI'
00306     2006-06-30    fixed silly bug in card detect & write protect detection routines
00307     2006-06-27    changed the ADC registers to the correct 18F2620 ADC registers settings (the 18F2620 has not 2 but 3 regsiters)
00308     2006-06-23    changed the device to 18F2620 (the prototype device was 18252 the 2620 can do MUCH more for allmost the same price)
00309                 removed the small demo-sequence
00310     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"
00311     2006-04-20    improvement in startup screen, now the splash screen stays partially visible exposing only the 1541-III logo (nice)
00312     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
00313                 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!!)
00314     2006-04-02    added extra display functionality, like a progress bar (for loading and saving)
00315     2006-03-31    2nd day of testing the nokia 3310 lcd, it works
00316     2006-02-28    some modifications required for the new PCB design and some testing routines
00317     2006-03-13    when the user tries to acces a directory that is not there, future actions will refer to the card.
00318     2006-03-10    the file not found problem solved, I needed to release the bus, hurray. Attila, thanks for the information, really appreciate it
00319     2006-02-22    added frame_handshake signal for later use (trying to solve the file not found situation)
00320     2006-02-20  Loading of .PRG files is now possible, the search routine will check the filename up to the first 8 chars
00321                 Preparing INT0 for interrupt handling of the ATN-line
00322     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
00323     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!!
00324                 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)
00325     2006-2-9/17    Nothing, code is stable now, do nothing untill the presentation at commodore GG has passed
00326     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
00327                 added the DOT in the 8.3 filename representation in the 'card directory' routine, also added an extra space for better alligment
00328     2006-02-07    added file selection directly (and only) after reset
00329                 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)
00330     2006-02-05    added LED blinking codes to the existing error messages
00331     2006-02-04    added interrupt routines to realise the LED blinking (req. for the original LED blinking error indicators)
00332     2006-02-03  implemented filter on filesize and extension, this means only D64 files are shown (command: LOAD"$0",DEVICE)
00333     2006-02-02    improvements in code layout... i.o.w. making it more readable, fixed some FAT bugs, tremendous speed improvement !!!
00334                 Benchmark results:    |     filename         | #blocks |    1541-II  | 1541-III | Conclusion
00335                 --------------------+-------------------+---------+----------+----------+----------------
00336                                        |  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)
00337                                        |                   |         |          |          |
00338 
00339     2006-01-29  Removal of the redundant block_buffer and dat_buf registers, as a result of better 'fat' and 'ata' routines
00340     2006-01-26    Loading of deleted files was possible, this is now fixed
00341     2006-01-22    Adjusted the 'help' section in the $0 (card directory) for proper reading on a VC-20
00342     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'
00343     2006-01-19    removed unnecessary PRINTF's, added printf filename near LOADD64FILE
00344     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)
00345     2006-01-18    finished send-error-code routine (although Track and Sector are still hardcoded to 0
00346     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.
00347     2006-01-15  continued search for the 'loadin works only the first time' problem
00348     2006-01-12    renamed some routines, rewritten part of the statemachine
00349     2006-01-11    rewritten the main decoder loop (statemachine)
00350     2006-01-10    TALK and LISTEN definitions were mixed up, is corrected    improved the FreeIEC routine
00351     2006-01-09    interference problem with other devices on the bus has been solved
00352     2006-01-04    better command decoder
00353     2006-01-02    begining of real/serious command decoder
00354     2006-01-01    corrected small error in directory, now text allignment is correct
00355     2005-12-24  implementation of the actual directory of an D64 emulator file
00356     2005-12-22  fixed the directory, now we can load a dir into the C64
00357     2005-12-18  testing of the IEC-write and TurnAround routines
00358     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
00359     2005-09-20    raw design of fileselection routine
00360     2005-09-21    design of ADC button decoder
00361     2005-09-22    design of user interface
00362     2005-09-26    figured out how to read the disks name from the correct track sector
00363     2005-09-02    figured out how to decode the ImageDirectory, file by file, algoRITHM
00364     2005-09-02  started with the free sectors routine
00365 */
00366 
00367 /*  TO DO:
00368     ------
00369 
00370     for specific "to do" (pieces of missing code) use the following keyword (use search function of editor):
00371     //to do:
00372 
00373     -replace D64blockread functioncall(s) for D64blockread_new and discard the D64blockread, then rename the D64blockread_new to D64blockread
00374     -replace D64blockwrite functioncall(s) for D64blockwrite_new and discard the D64blockwrite, then rename the D64blockwrite_new to D64blockwrite
00375 
00376     - 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)
00377       so there are two options... leave out the index number or enlarge the indexnumber to 5 digits instead of 3
00378 
00379     - controleren of er nog (andere) plekken zijn waar "extractfilenamefromstring" gebruikt kan worden
00380     - 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
00381 
00382     - 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?
00383 
00384     - loading of a directory without typeing LOAD"$",8 (zie de boeken voor voorbeeld programma's)
00385     - 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 !?!?
00386 
00387     - the 1541-III fails to function in combination with a C128
00388 
00389     - 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?
00390       check for EOI bij elke stap
00391 
00392     - Make note in manual about unrecognised characters (see bugfix of 2006-11-03)
00393 
00394     - support for eror-bytes in extended 35- and 40-track .D64 files
00395 */
00396 
00397 /*    Notes to myself:
00398     ----------------
00399     -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
00400 
00401     -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)
00402 
00403 */
00404 
00405 /*----------------------------------------------------------------------------------*/
00406 
00407 // example of sd card access
00408 #include "mbed.h"
00409 #include <main.h>
00410 #include <hardware.h>
00411 #include <delay.h>
00412 #include <ata.h>
00413 #include <fat.h>
00414 #include <D64_decoder.h>
00415 #include <T64_decoder.h>
00416 #include <IEC_bus.h>
00417 
00418 // #include "string"
00419 // #include "SDHCFileSystem.h"
00420 //
00421 // SDFileSystem sd(p5, p6, p7, p8, "sd"); // mosi, miso, sclk, cs
00422 //
00423 // int main() {
00424 //
00425 //       FILE *fp = fopen("/sd/myfile.txt", "w");
00426 //       fprintf(fp, "\n\rHello World!\n\r");
00427 //       fclose(fp);
00428 // }
00429 // IEC hardware connections
00430 DigitalInOut nSRQ(p18);     // DIN6 pin 1
00431 DigitalInOut nATN(p17);     // DIN6 pin 3
00432 DigitalInOut nCLK(p16);     // DIN6 pin 4
00433 DigitalInOut nDATA(p15);    // DIN6 pin 5
00434 // DigitalInOut nRESET(p19);
00435 
00436 InterruptIn nIRQ(p30);      // external loop: connect to nATN
00437 InterruptIn nRESET(p29);    // DIN6 pin 6
00438 
00439 DigitalIn JUMPER_J2(p21);
00440 DigitalIn JUMPER_J3(p22);
00441 
00442 DigitalOut myled1(LED1);
00443 DigitalOut myled2(LED2);
00444 DigitalOut myled3(LED3);
00445 DigitalOut myled4(LED4);
00446 
00447 #define LED_GREEN myled1
00448 #define LED_RED   myled2
00449 
00450 Timer timeout;
00451 Serial linktopc(USBTX,USBRX);
00452 
00453 // #define IEC_ATN_REL()    IEC_DDR &= ~IEC_BIT_ATN
00454 void IEC_ATN_REL() {
00455     nATN=1;
00456     nATN.input();
00457 }
00458 
00459 // #define IEC_ATN_PULL()   IEC_DDR |= IEC_BIT_ATN
00460 void IEC_ATN_PULL() {
00461     nATN.output();
00462     nATN=0;
00463 }
00464 
00465 // #define IEC_CLOCK_REL()  IEC_DDR &= ~IEC_BIT_CLOCK
00466 void IEC_CLOCK_REL() {
00467     nCLK=1;
00468     nCLK.input();
00469 }
00470 
00471 // #define IEC_CLOCK_PULL() IEC_DDR |= IEC_BIT_CLOCK
00472 void IEC_CLOCK_PULL() {
00473     nCLK.output();
00474     nCLK=0;
00475 }
00476 
00477 // #define IEC_DATA_REL()   IEC_DDR &= ~IEC_BIT_DATA
00478 void IEC_DATA_REL() {
00479     nDATA=1;
00480     nDATA.input();
00481 }
00482 
00483 // #define IEC_DATA_PULL()  IEC_DDR |= IEC_BIT_DATA
00484 void IEC_DATA_PULL() {
00485     nDATA.output();
00486     nDATA=0;
00487 }
00488 
00489 void IEC_SRQ_REL() {
00490     nSRQ=1;
00491     nSRQ.input();
00492 }
00493 
00494 void IEC_SRQ_PULL() {
00495     nSRQ.output();
00496     nSRQ=0;
00497 }
00498 
00499 int IEC_ATN() {
00500     nATN.input();
00501     return    nATN;
00502 }
00503 
00504 int IEC_CLOCK() {
00505     nCLK.input();
00506     return  nCLK;
00507 }
00508 
00509 int IEC_DATA() {
00510     nDATA.input();
00511     return   nDATA;
00512 }
00513 
00514 int IEC_SRQ() {
00515     nSRQ.input();
00516     return nSRQ;
00517 }
00518 
00519 /*--------------------------------------------------------*/
00520 /*                       EEPROM                           */
00521 /*--------------------------------------------------------*/
00522 /*
00523 __EEPROM_DATA('-','-','-','-','-','-','-','-');
00524 __EEPROM_DATA('-','-','-','-','-','-','-','-');
00525 __EEPROM_DATA('-','-','-','-','-','-','-','-');
00526 __EEPROM_DATA('-','-','-','-','-','-','-','-');
00527 __EEPROM_DATA('-','-','-','-','-','-','-','-');
00528 */
00529 /*--------------------------------------------------------*/
00530 
00531 /*--------------------------------------------------------*/
00532 /*                        constants                       */
00533 /*--------------------------------------------------------*/
00534 
00535 #define            FALSE                0            /*FALSE*/
00536 #define            TRUE                1            /*TRUE*/
00537 
00538 /*--------------------------------------------------------*/
00539 
00540 /*PCB types and versions*/
00541 enum PCBTYPE {v1=10, v1_1, DTV, DTV_C64};
00542 
00543 /*defines for the IEC-bus statemachine*/
00544 enum IEC_bus_statemachine {IDLE=0, ACTIVE_LISTEN, ACTIVE_TALK};
00545 
00546 /*blink modes*/
00547 enum LED_modes {LED_OFF=0, LED_ON, LED_ERROR, LED_GR, LED_RD, LED_OR};
00548 
00549 /*disk-state*/
00550 enum DiskState {NO_CARD=0, CARD_ACTIVE, INVALID_POINTER};
00551 
00552 /*1541-III commands*/
00553 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};
00554 
00555 /*filetypes*/
00556 enum Filetypes {SEQUENTIAL=1, RELATIVE, PROGRAM, USER, LENGTH};
00557 
00558 /*--------------------------------------------------------*/
00559 
00560 #define            BUTTON_SELECTION_RATE 350        /*this value determines the button repetition rate*/
00561 
00562 /*MMC/SD-card*/
00563 #define            MMCCARD                2            /*card type found reference*/
00564 #define            SDCARD                3            /*card type found reference*/
00565 #define            FILENOTFOUND         4            /*filenotfound reference*/
00566 #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*/
00567 
00568 /*buttons*/
00569 #define            button_none            0            /*numerical value of ADC when no button is pressed*/
00570 #define            button_tolerance    15            /*max. alowable deviation of expected button values*/
00571 #define            button_1             870            /*numerical value of ADC when button-1 is pressed*/
00572 #define            button_2            721            /*numerical value of ADC when button-2 is pressed*/
00573 #define            button_3            575            /*numerical value of ADC when button-3 is pressed*/
00574 #define            button_4            431            /*numerical value of ADC when button-4 is pressed*/
00575 #define            button_5             288            /*numerical value of ADC when button-5 is pressed*/
00576 #define            button_6            145            /*numerical value of ADC when button-6 is pressed*/
00577 
00578 /*1541-III operational modes/filefilter results*/
00579 #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*/
00580 #define            PRG_FILE            1
00581 #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*/
00582 #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*/
00583 #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*/
00584 #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*/
00585 #define            T64_MODE            6        /*the 1541-III has opened a .T64 file*/
00586 #define            SUBDIRECTORY        100        /*the 1541-III has encountered a subdirectory*/
00587 #define            UNKNOWN                255        /*the 1541-III has encountered a file that has no extension*/
00588 
00589 #define            FILE_NOT_PRESENT    0
00590 #define            FILE_PRESENT        1
00591 
00592 /*text printing definitions*/
00593 #define            PLAIN                0
00594 #define            BOLD                1
00595 #define            INVERTED            2
00596 
00597 /*--------------------------------------------------------*/
00598 /*                         macro's                        */
00599 /*--------------------------------------------------------*/
00600 #define            disable()     GIE=0                /*disable interrupts*/
00601 #define            enable()     GIE=1                /*enable interrupts*/
00602 
00603 /*--------------------------------------------------------*/
00604 /*                         globals                        */
00605 /*--------------------------------------------------------*/
00606 
00607 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*/
00608 //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)*/
00609 unsigned char     block_buffer[512];            /*this buffers the data 'as read from' or 'to be written to' the card*/
00610 struct            DOS_buffer_struct    DOS_buffer[MAX_NUMBER_OF_DOS_BUFFERS];    /*this array of structs holds the information about the possible channels*/
00611 struct            DOS_channel_struct    DOS_channel[16];                        /*this array of structs holds this information about the currently used channels*/
00612 
00613 /*--------------------------------------------------------*/
00614 unsigned char     PCB_type;                    /*this value contains the PCB type/version*/
00615 unsigned int    PCB_type_timer;                /*this timer determines the actual PCB type detection*/
00616 unsigned char    setting_contrast;            /*this is the value belonging to the contrast setting as found in EEPROM*/
00617 unsigned char    VIC20_mode;                    /*this is the value belonging to the IEC-speed setting as found in EEPROM*/
00618 
00619 unsigned char    devicenumber;                /*this var. holds the device number 8,9,10 or 11*/
00620 unsigned char    device_command;
00621 
00622 unsigned char    IEC_state;                    /*talk, listen or idle*/
00623 unsigned char    channel;                    /*this register holds the channel value*/
00624 unsigned char    nextfreebuffer;                /*this register holds the buffernumber of the next buffer to be used*/
00625 unsigned char    ChannelUsesBuffer[16];        /*small array to keep track of which channel uses what buffer (to drive you mad... MAD I SAY!$#%$#%$#$%#)*/
00626 unsigned char    command;                    /*this is the unfiltered (as received for the IEC-bus) command*/
00627 unsigned char    command_string[41];            /*this string holds the command details/options*/
00628 unsigned char    filename_string[41];        /*this string (is suppost to) hold(s) the filename*/
00629 unsigned char    oldfilename_string[41];        /*this string (is suppost to) hold(s) the new filename (for renaming routines)*/
00630 unsigned char    value_string[17];            /*this string (is suppost to) hold(s) a value*/
00631 unsigned char    string_pntr;
00632 unsigned char    string_pntr_2;
00633 unsigned long    value_long;
00634 unsigned char    value_1;
00635 unsigned char    value_2;
00636 unsigned char    value_3;
00637 unsigned char    value_4;
00638 unsigned char    filetype_string[41];        /*filetype can be sequential, program, user, etc.*/
00639 unsigned char    RW_string[41];                /*file read or write*/
00640 
00641 unsigned char    error_code = 73;            /*this holds the error-message generated by one of the disk routines*/
00642 unsigned char    LastTrack = 0;                /*last accessed track variable*/
00643 unsigned char    LastSector = 0;                /*last accessed sector variable*/
00644 unsigned char    files_scratched = 0;        /**/
00645 
00646 unsigned char    Response_data[5];
00647 
00648 unsigned char    file_type;                    /*this holds the type of the current file or NONE if no file is selected*/
00649 unsigned int    file_number;                /*the current file index number, this number is used as a reference for button actions*/
00650 unsigned int    CountedFiles;                /*the number of files in the current (root/sub)-directory*/
00651 
00652 struct             file2TYPE             file;        /*file handle*/
00653 struct            directory_entry        dir_entry;    /*directory structure inside the D64*/
00654 
00655 bit                button_prev;
00656 bit                button_select;
00657 bit                button_next;
00658 
00659 unsigned char    Blink_mode;                    /*mode of operation of the blink routine*/
00660 bit                Blink_dir;                    /*direction of intensity change (up or down)*/
00661 unsigned char    Blink_block;                /*holds the byte-number on which the LED should go off in order to create a blink at every block*/
00662 unsigned char    LED_OFF_delay;                /*holds the delay timing value for the LED-OFF time*/
00663 bit                LED_status;                    /*the current state of the LED is stored here*/
00664 unsigned char    LED_color;                    /*value to keep track of current LED-color*/
00665 unsigned char    next_LED_color;                /*value to keep track of current LED-color*/
00666 unsigned char    DiskState;                    /*state of the disk (image) inside the drive (1541-III)*/
00667 
00668 bit             EOI;                        /*End Of Indicator: this flag (when TRUE) indicates that the last byte is being transmitted or received*/
00669 bit             TimeOut;                    /*Timeout-flag*/
00670 
00671 unsigned char     dirtrack, dirsector, direntry;
00672 unsigned long    lp, lp2;
00673 unsigned int    blocksize;
00674 unsigned char    track, sector;
00675 unsigned char    file_status;
00676 
00677 /*--------------------------------------------------------*/
00678 /*                     local functions                    */
00679 /*--------------------------------------------------------*/
00680 void WaitForString(unsigned char *outputstring, unsigned frame_handshake);
00681 unsigned char ValueFromString(unsigned char *inputstring, unsigned char *outputvalue);
00682 unsigned char LongValueFromString(unsigned char *inputstring, unsigned long *outputvalue);
00683 void ExtractFilenameFromString(unsigned char *input_string, unsigned char *output_string);
00684 unsigned char SplitStringOn_Sign(unsigned char sign, unsigned char *beforesign_string, unsigned char *aftersign_string);
00685 
00686 void IEC_direction_statemachine(void);
00687 void OpenHandler(void);
00688 void DataHandler(void);
00689 void AutoDetectPcbType(void);
00690 void NoCardMenu(void);
00691 void HardWareTestMenu(void);
00692 unsigned char CardStatus(void);
00693 void CountFiles(void);
00694 unsigned char Init_Card_SPI(void);
00695 unsigned char FileFilter(void);
00696 
00697 unsigned char SearchFreeBuffer(void);
00698 
00699 void Clear_block_buffer(void);
00700 void SelectD64Image(void);
00701 void CardDirectory(void);
00702 void D64Directory(void);
00703 void T64Directory(void);
00704 unsigned int SeekFileOnCard(unsigned char *filename, struct file2TYPE *file);
00705 void LoadFileFromCard(struct file2TYPE *file);
00706 void LoadD64File(unsigned char trk, unsigned char sec, unsigned int filesizeinblocks);
00707 unsigned char SaveD64File(void);
00708 unsigned char CopyD64File(unsigned char trk, unsigned char sec, unsigned int filesizeinblocks);
00709 
00710 void SetErrorCode(unsigned char error, unsigned char LEDmode);
00711 void SendErrorMessage(void);
00712 
00713 void print_device_status(const unsigned char *message);
00714 void print_D64_name(unsigned char mode);
00715 void print_D64_TSB(unsigned char trk, unsigned char sec, unsigned int blk, unsigned int total_blk);
00716 
00717 unsigned char ReadDeviceJumper(void);
00718 unsigned char ReadButtons(void);
00719 
00720 void FormatD64File(unsigned char *diskname, unsigned char *diskid);
00721 /*****************************************************************************************************************/
00722 /*****************************************************************************************************************/
00723 /*****************************************************************************************************************/
00724 /*Interrupt service routines*/
00725 /*****************************************************************************************************************/
00726 /*****************************************************************************************************************/
00727 /*Low-priority interrupt entry point*/
00728 void NotTimeCritical(void) {
00729 
00730 }
00731 
00732 /*High-priority interrupt entry point*/
00733 void high_priority(void) {
00734     unsigned char    filter_cnt;
00735     /*By putting the ATN-line detection on an interrupt-line we detect the ATN-situation independent of*/
00736     /*other actions, like selecting a new D64 image. This method makes IEC programming less complex*/
00737     /*the small filter also creates a hold-off time, for some reason this is required*/
00738     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*/
00739     while (IEC_ATN() == 0) {         /*although this filter does add some latency to the start of a data transfer, it is not noticeable in practice*/
00740         /*it does however add a more secure ATN-line detection, since the inputlines are not filtered in any other way*/
00741         wait_us(1);
00742         filter_cnt--;
00743         if (filter_cnt == 0)    /*when the ATN signal has been proven not to be a glitch*/
00744         {                        /*we can safely handle the ATN-signal*/
00745             IEC_DATA_PULL();/*join the bus...*/
00746             myled3=1;
00747 
00748             break;
00749         }
00750     }
00751 }
00752 
00753 extern "C" void mbed_reset();
00754 
00755 void iec_reset_interrupt(void) {
00756     nIRQ.fall(NULL);
00757     nRESET.fall(NULL);
00758     mbed_reset();
00759 }
00760 
00761 /*macro*/
00762 // #define        disable_ATN_interrupt()    INT0IE = 0    /*disable interrupts on ATN line*/
00763 // #define        enable_ATN_interrupt()    INT0IE = 1    /*enable interrupts on ATN line*/
00764 
00765 void enable_ATN_interrupt() {
00766     nIRQ.mode(PullUp);
00767     nIRQ.fall(&high_priority);
00768 }
00769 
00770 void enable_RESET_interrupt() {
00771     nRESET.mode(PullUp);
00772     nRESET.fall(&iec_reset_interrupt);
00773 }
00774 
00775 void disable_ATN_interrupt() {
00776     nIRQ.fall(NULL);
00777 }
00778 /*****************************************************************************************************************/
00779 /*****************************************************************************************************************/
00780 /*Main*/
00781 /*****************************************************************************************************************/
00782 /*****************************************************************************************************************/
00783 
00784 int main(void) {
00785 
00786     HardwareInit();                                    /*init controller registers and I/O-lines*/
00787 //    GetSettingsFromEEPROM();                        /*read EEPROM settings*/
00788     devicenumber = ReadDeviceJumper();                /*read the devicenumber jumper*/
00789     InitIEC();                                        /*initialize the IEC-bus levels*/
00790     /*initialize SPI*/
00791 
00792 
00793     linktopc.baud(115200);
00794 
00795     timeout.start();     // start timer
00796 
00797 //   InitLcd();                                        /*initialize the LCD*/
00798     AutoDetectPcbType();                            /*measure the button capacitor to determine PCB type*/
00799     OutputToRS232();                                /*set standard output to RS232*/
00800     printf("\r\n  -----------------------------------------");
00801     printf("\r\n |                                         |");
00802     printf("\r\n |                                         |");
00803     printf("\r\n |        --==   1541 - III    ==--        |");
00804     printf("\r\n |             (by J.Derogee)              |");
00805     printf("\r\n |      (http://jderogee.tripod.com)       |");
00806     printf("\r\n |                                         |");
00807     printf("\r\n |                                         |");
00808     printf("\r\n |                                         |");
00809     printf("\r\n |                                         |");
00810     printf("\r\n |                                         |");
00811     printf("\r\n |                                         |");
00812     printf("\r\n |                                         |");
00813     printf("\r\n |                                         |");
00814     printf("\r\n |                                         |");
00815     printf("\r\n |                                         |");
00816     printf("\r\n |     --------------------------------    |");
00817     printf("\r\n | ( ) |Firmware vers.: v20%02d-%02d-%02d   |    |",RELEASE_VERSION,RELEASE_VERSION_SUB,RELEASE_VERSION_SUB_SUB);
00818     printf("\r\n |     |J2 (Device-ID): ID=%1d          |    |",devicenumber);
00819     printf("\r\n |     |J3 (Bootldr)  : ");
00820     if (JUMPER_J3 == 0)
00821         printf("ACTIVE        |    |");
00822     else
00823         printf("DISABLED      |    |");
00824 
00825     printf("\r\n | ( ) |Contrast      : 0x%02x          |    |",setting_contrast);    /*show the settings*/
00826     printf("\r\n |     |VIC20-mode    : ");
00827     if (VIC20_mode == TRUE)
00828         printf("TRUE          |    |");
00829     else
00830         printf("FALSE         |    |");
00831 
00832     printf("\r\n |     |PCB type det. : %05d         |    |",PCB_type_timer);    /*check which kind of PCb we are dealing with...*/
00833 
00834     /*adjust the startup sequence accordingly and settings depending on the PCB version*/
00835     if (PCB_type == v1) {
00836         printf("\r\n | ( ) |Detected PCB  : 1541-III v1.0 |    |");
00837 //        Lcd_show_1541_III();                        /*show splash screen*/
00838         SetIEC_timings(TIMINGS_DEFAULT);            /*set timings to default*/
00839         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*/
00840     }
00841 
00842     if (PCB_type == v1_1) {
00843         printf("\r\n | ( ) |Detected PCB  : 1541-III v1.1 |    |");
00844         //      Lcd_show_1541_III();                        /*show splash screen*/
00845         SetIEC_timings(TIMINGS_DEFAULT);            /*set timings to default*/
00846         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*/
00847     }
00848 
00849     if (PCB_type == DTV) {
00850         printf("\r\n | ( ) |Detected PCB  : 1541-III DTV  |    |");
00851         //    Lcd_show_1541_III_DTV();                    /*show splash screen*/
00852         SetIEC_timings(TIMINGS_DTV);                /*set timings according the settings as requested by Jussi (DTV tested settings)*/
00853         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*/
00854     }
00855 
00856     if (PCB_type == DTV_C64) {
00857         printf("\r\n | ( ) |Detected PCB : 1541-III DTV   |    |");
00858         //  Lcd_show_1541_III_DTV();                     /*show splash screen*/
00859         SetIEC_timings(TIMINGS_DEFAULT);             /*set default timings */
00860         Blink_block = 235;
00861     }
00862 
00863     printf("\r\n |     --------------------------------    |");
00864     printf("\r\n |                                         |");
00865     printf("\r\n |     O                             O     |");
00866     printf("\r\n |   POWER                         DRIVE   |");
00867     printf("\r\n |                                         |");
00868     printf("\r\n  -----------------------------------------");
00869     printf("\r\n");
00870 
00871     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*/
00872         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*/
00873     /*set timings according the VIC-20 settings (25% faster mode)*/
00874 
00875     printf("\r\n");                                    /*set cursor to the beginning of the next line (prepare for future (optional) debug printing)*/
00876     OutputToLCD();                                    /*set standard output to LCD*/
00877     SetErrorCode(73, LED_ON);                        /*all is OK, but show ID first, LED is ON as on a real 1541*/
00878 
00879     for (lp=0; lp<MAX_NUMBER_OF_DOS_BUFFERS; lp++) { /*clear the channels*/
00880         DOS_channel[lp].channel_in_use = FALSE;
00881         DOS_channel[lp].filename[0] = 0;
00882         DOS_channel[lp].filetype = 0;
00883         DOS_channel[lp].RW = 0;
00884         DOS_channel[lp].track = 0;
00885         DOS_channel[lp].sector = 0;
00886         DOS_channel[lp].buffer_pointer = 0;
00887         DOS_channel[lp].used_buffer = 255;
00888         DOS_channel[lp].status = NO_FILE;
00889     }
00890 
00891     for (lp=0; lp<5; lp++) {                         /*clear the buffers*/
00892         DOS_buffer[lp].buffer_in_use = FALSE;
00893         for (lp2=0; lp2<256; lp2++) {
00894             DOS_buffer[lp].buffer[lp2] = 0;
00895         }
00896     }
00897     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*/
00898 
00899     // 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)*/
00900     IEC_state = IDLE;
00901     file_type = NONE;                                /*after reset or card insertion there is no D64 file selected, so all actions regarding current refer to the card*/
00902     DiskState = NO_CARD;                            /*no card detected yet, so no D64 is selected*/
00903     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*/
00904     enable_ATN_interrupt();                            /*enabling the interrupt makes the system ready for use on the IEC-bus*/
00905     enable_RESET_interrupt();
00906     
00907     while (1) {
00908         IEC_direction_statemachine();
00909     }
00910 }
00911 
00912 /*****************************************************************************************************************/
00913 /*****************************************************************************************************************/
00914 #define CARD_DETECT 0   // this should be a hardware pin
00915 
00916 void IEC_direction_statemachine(void) {
00917     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*/
00918 //    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*/
00919     device_command = CheckForCommand(&command, TRUE);
00920     while (device_command == FALSE) {                      /*no commands are received so we have time for others things...*/
00921 
00922         if (CARD_DETECT == 1)                           /*check if the card is present*/
00923             DiskState = NO_CARD;                        /*no card detected, so no D64 is selected*/
00924 
00925         if (DiskState == NO_CARD) {
00926             DelayBigMs(1000);
00927             SetErrorCode(73, LED_OFF);                    /*all is OK, but show ID first, LED is OFF as on a real 1541*/
00928             //   Lcd_clr();                                    /*clear screen to prepare for more serious info.*/
00929             NoCardMenu();                                /*check if a setting button has been pressed and handle accordingly*/
00930             if (CardStatus()) {                          /*this routine will only pass until a valid card is present*/
00931                 CountFiles();                            /*count all files in the current directory (which is root)*/
00932                 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)*/
00933                 file_type = NONE;                    /*after reset or card insertion there is no D64 file selected, so all actions regarding current refer to the card*/
00934                 //        Lcd_clr();
00935                 print_D64_name(PLAIN);
00936                 print_D64_TSB(0, 0, 0,0);                /*print Track, Sector, Block*/
00937             }
00938         }
00939 //       else
00940 //       {
00941 //           SelectD64Image();                            /*check for user interaction via buttons*/
00942 //       }
00943         device_command = CheckForCommand(&command, TRUE);
00944     }
00945 
00946     if (CARD_DETECT == 1)                               /*check again if the card is present, some @#$#@$#@% might have removed it*/
00947         DiskState = NO_CARD;                            /*no card detected, so no D64 is selected*/
00948 
00949 
00950     switch (device_command) {
00951         case OPEN: {  /*here we decode the command string and we check if we are capable of executing the requested action*/
00952             DOS_channel[channel].channel_in_use = TRUE;        /*claim this channel*/
00953             WaitForString(command_string, TRUE);            /*wait for an operator string that ends with an EOI*/
00954             break;
00955         }
00956 
00957         case DATA: {
00958 //            if (DOS_channel[channel].channel_in_use == TRUE)    /*check if this channel has been opened, if not ignore*/
00959 //            {
00960             DataHandler();
00961 //            }
00962 //            else
00963 //            {
00964 //                OutputToRS232();                                        /*set standard output to RS232*/
00965 //                printf("\r\nChannel not open! Ignore DATA command");    /*!!! DEBUG ONLY !!!*/
00966 //                OutputToLCD();                                            /*set standard output to LCD*/
00967 //            }
00968             break;
00969         }
00970 
00971         case CLOSE: {
00972 //            if (channel == 15)                                    /*when the error/command channel is closed, then all files stored in the DOS buffer are closed also*/
00973 //            {
00974             /*to do: close all open files properly*/
00975 //            }
00976 //            else
00977 //            {
00978 //            }
00979 
00980             if (DOS_channel[channel].used_buffer != 255) {  /*check if there is a buffer connected to this channel*/
00981                 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*/
00982             }
00983 
00984             /*set the channel information back to default, although i doubt that the original 1541 does this...*/
00985             DOS_channel[channel].channel_in_use = FALSE;
00986             DOS_channel[channel].filename[0] = 0;
00987             DOS_channel[channel].filetype = 0;
00988             DOS_channel[channel].RW = 0;
00989             DOS_channel[channel].track = 0;
00990             DOS_channel[channel].sector = 0;
00991             DOS_channel[channel].buffer_pointer = 0;
00992             DOS_channel[channel].used_buffer = 255;
00993             DOS_channel[channel].status = NO_FILE;
00994 
00995             OutputToRS232();                        /*set standard output to RS232*/
00996             printf("\r\nClose");                    /*!!! DEBUG ONLY !!!*/
00997             OutputToLCD();                            /*set standard output to LCD*/
00998             break;
00999         }
01000 
01001         case UNLISTEN: {
01002             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*/
01003                 if (DOS_channel[channel].channel_in_use == TRUE) {  /*check if the previous command on this channel was open*/
01004                     OpenHandler();
01005                 }
01006 
01007                 //turn LED OFF
01008 //    OutputToRS232();                /*set standard output to RS232*/
01009 //    printf("\r\nUnlisten\r\n");            /*!!! DEBUG ONLY !!!*/
01010 //    OutputToLCD();                    /*set standard output to LCD*/
01011                 IEC_state = IDLE;
01012             }
01013             break;
01014         }
01015 
01016         case UNTALK: {
01017             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*/
01018                 //turn LED OFF
01019                 IEC_state = IDLE;
01020 //    OutputToRS232();                    /*set standard output to RS232*/
01021 //    printf("\r\nUntalk\r\n");                /*!!! DEBUG ONLY !!!*/
01022 //    OutputToLCD();                        /*set standard output to LCD*/
01023 
01024             }
01025             break;
01026         }
01027 
01028         default: {
01029             if (device_command == (LISTEN | devicenumber)) {
01030                 //turn LED ON
01031                 IEC_state = ACTIVE_LISTEN;
01032 //    OutputToRS232();                /*set standard output to RS232*/
01033 //    printf("\r\nListen");            /*!!! DEBUG ONLY !!!*/
01034 //    OutputToLCD();                    /*set standard output to LCD*/
01035                 break;
01036             }
01037 
01038             if (device_command == (TALK | devicenumber)) {
01039                 //turn LED ON
01040                 IEC_state =    ACTIVE_TALK;
01041 //    OutputToRS232();                /*set standard output to RS232*/
01042 //    printf("\r\nTalk");                /*!!! DEBUG ONLY !!!*/
01043 //    OutputToLCD();                    /*set standard output to LCD*/
01044                 break;
01045             }
01046 
01047             /*--------------------------------------------------------------------------------------*/
01048             /* current communication on the bus is incorrect or meant for another device on the bus */
01049             /*--------------------------------------------------------------------------------------*/
01050             disable_ATN_interrupt();    /*By disabling the ATN interrupt we do not interfer with the data that is meant for another device on the bus*/
01051             FreeIEC();                    /*get of the bus...*/
01052             enable_ATN_interrupt();        /*all is back to normal, enable interrupts on ATN line*/
01053             IEC_state = IDLE;
01054             break;
01055         }
01056     }
01057 
01058     myled3=0;
01059 }
01060 
01061 
01062 void OpenHandler(void) {
01063 //    OutputToRS232();                        /*set standard output to RS232*/
01064 //    printf("\r\nOPENHANDLER: ");                /*!!! DEBUG ONLY !!!*/
01065 //    printf("command_string:%s",command_string);    /*!!! DEBUG ONLY !!!*/
01066 //    printf("\r\nchannel:%d",channel);        /*!!! DEBUG ONLY !!!*/
01067 //    OutputToLCD();                            /*set standard output to LCD*/
01068 
01069     switch (channel) {
01070         case 0: {              /*this channel is used for reading of files*/
01071             if (DiskState == NO_CARD) {
01072                 DOS_channel[channel].next_action = ABORT_SENDING;
01073                 break;
01074             }
01075 
01076             /*------------------*/
01077             /* '$' = DIRECTORY  */
01078             /*------------------*/
01079             if ((strlen((char *)command_string) == 5) && (strncmp((char *)command_string,"$CARD", 5) == 0 ))        /*check the COMPLETE string*/
01080             {    /*ROOT directory of the card*/
01081                 file_type = NONE;                                        /*all later actions refer to the CARD and not a D64 file*/
01082                 DiskState = CARD_ACTIVE;                                    /*this command overrules the buttons*/
01083                 DOS_channel[channel].next_action = CARD_DIRECTORY;            /*show the directory of the MMC/SD-card*/
01084                 print_D64_name(PLAIN);
01085                 break;
01086             }
01087 
01088             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*/
01089             {    /*current directory, which may be D64 or ROOT depending on the previous selection*/
01090                 if ((file_type == NONE) || (file_type == SUBDIRECTORY))        /*check for the currently selected file, if 0 refer to the card and not a D64 file*/
01091                     DOS_channel[channel].next_action = CARD_DIRECTORY;        /*show the directory of the MMC/SD-card*/
01092                 else
01093                     DOS_channel[channel].next_action = DIRECTORY;            /*show the directory of the currently selected D64 file*/
01094                 break;
01095             }
01096 
01097             if (strncmp("$", (char *)command_string, 1) == 0 ) {                      /*check the 1st char of the string)*/
01098                 file_status = SeekFileOnCard(&command_string[1], &file);    /*check if file is present or not*/
01099                 if (file_status == FALSE) {
01100                     SetErrorCode(62,LED_ERROR);                                /*file not found*/
01101                     DOS_channel[channel].next_action = ABORT_SENDING;        /*the requested directory does not exist*/
01102                 } else {
01103                     DiskState = CARD_ACTIVE;                                /*this command overrules the buttons*/
01104                     file_type = FileFilter();                                /*check the type of file to determine the mode of operation*/
01105                     if (file_type == SUBDIRECTORY) {                         /*check if the user wants to enter a subdirectory*/
01106                         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*/
01107                         file_number = 0;                                    /*the file_number counter needs to be reset*/
01108                         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*/
01109                         CountFiles();                                        /*count all files in the opened directory*/
01110                         DOS_channel[channel].next_action = CARD_DIRECTORY;    /*show the (sub)directory of the MMC/SD-card*/
01111                         print_D64_name(PLAIN);                                /*update the display*/
01112                     } else {
01113                         file_number = file_status;
01114                         DOS_channel[channel].next_action = DIRECTORY;        /*show the directory of the requested D64 file (but only if the actions below do not fail offcourse)*/
01115                         print_D64_name(PLAIN);                                /*update the display*/
01116                         FileSectorScan(&file);                                /*update the sector location table cache*/
01117                         D64ReadBAM();                                        /*update the BAM*/
01118                     }
01119                 }
01120                 break;                                                        /*leave the case*/
01121             }
01122 
01123             /*----------------------*/
01124             /* LOAD filename        */
01125             /*----------------------*/
01126             if (file_type == NONE) {                                      /*check for the currently selected file, if 0 refer to the card and not a D64 file*/
01127                 file_status = SeekFileOnCard(command_string, &file);    /*check if file is present on the card*/
01128                 DOS_channel[channel].next_action = RD_FILE_FROM_ROOT;
01129                 break;
01130             } else {
01131                 file_status = D64SeekFile(command_string, &track, &sector, &blocksize, &dirtrack, &dirsector, &direntry);    /*check if file is present within a D64 file*/
01132                 DOS_channel[channel].next_action = RD_FILE;
01133                 break;
01134             }
01135         }
01136 
01137         case 1: {              /*this channel is used for writing of files*/
01138             if (DiskState == NO_CARD) {
01139                 DOS_channel[channel].next_action = ABORT_RECEIVING;
01140                 break;
01141             }
01142 
01143             /*------------------------------------------------------------*/
01144             /* '@' = REPLACE                                              */
01145             /* syntax: SAVE"@0:<filename>",x,1                            */
01146             /* syntax: SAVE"@S:<filename>",8,1 (special for game:commando, int karate, donkey kong)*/
01147             /*------------------------------------------------------------*/
01148             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)*/
01149                 SplitStringOn_Sign(':', command_string, filename_string);
01150                 file_status = D64SeekFile(filename_string, &track, &sector, &blocksize, &dirtrack, &dirsector, &direntry);    /*check if file is present or not*/
01151                 DOS_channel[channel].next_action = REPLACE_FILE;                            /*replace a file within the currently selected D64 file*/
01152                 break;
01153             }
01154 
01155             /*---------------*/
01156             /* SAVE filename */
01157             /*---------------*/
01158             if (file_type == NONE) {      /*check for the currently selected file, if 0 refer to the card and not a D64 file*/
01159                 file_status = SeekFileOnCard(command_string, &file);    /*check if file is present or not*/
01160                 DOS_channel[channel].next_action = WR_FILE_TO_ROOT;
01161                 break;
01162             } else {
01163                 file_status = D64SeekFile(command_string, &track, &sector, &blocksize, &dirtrack, &dirsector, &direntry);    /*check if file is present or not*/
01164                 DOS_channel[channel].next_action = WR_FILE;
01165                 break;
01166             }
01167         }
01168 
01169 
01170         /*the channels 2-14 are used for the actual file handling that do not use the BASIC LOAD or SAVE commands*/
01171         case 2:
01172             ;
01173         case 3:
01174             ;
01175         case 4:
01176             ;
01177         case 5:
01178             ;
01179         case 6:
01180             ;
01181         case 7:
01182             ;
01183         case 8:
01184             ;
01185         case 9:
01186             ;
01187         case 10:
01188             ;
01189         case 11:
01190             ;
01191         case 12:
01192             ;
01193         case 13:
01194             ;
01195         case 14: {
01196             if (command_string[0] == '#') {                                      /*if the user/computer specifies a buffer then handle accordingly...*/
01197                 if (DOS_channel[channel].used_buffer == 255) {                  /*check if this channel allready has a buffer connected*/
01198                     if (ValueFromString(&command_string[0], &value_1)) {          /*check if the user has specified it's own buffer preference*/
01199                         if (DOS_buffer[value_1].buffer_in_use == FALSE) {          /*check if this buffer is still available*/
01200                             DOS_buffer[value_1].buffer_in_use = TRUE;            /*this buffer is still free, so we can claim this buffer*/
01201                             DOS_channel[channel].used_buffer = value_1;            /*connect the free buffer to this channel*/
01202                         } else {
01203                             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*/
01204                         }
01205                     } else {
01206                         nextfreebuffer = SearchFreeBuffer();                    /*since the user does not care which buffer it uses, so the 1541-III may decide which buffer is available*/
01207                         if (nextfreebuffer == 255) {
01208                             SetErrorCode(70, LED_ERROR);                        /*No channels available or in other words: no more free buffers */
01209                         } else {
01210                             DOS_buffer[nextfreebuffer].buffer_in_use = TRUE;    /*claim this buffer*/
01211                             DOS_channel[channel].used_buffer = nextfreebuffer;    /*connect the free buffer to this channel*/
01212                         }
01213                     }
01214                 }
01215             } else {
01216                 ExtractFilenameFromString(command_string, filename_string);    /*extract the filename from the commandstring given by the user/computer*/
01217                 SplitStringOn_Sign(',', command_string, filetype_string);
01218                 SplitStringOn_Sign(',', filetype_string, RW_string);
01219                 strcpy((char *)&DOS_channel[channel].filename[0], (char *)filename_string);    /*copy the filename into the DOS buffer*/
01220 
01221                 /*check for filetype*/
01222                 if ((strncmp("A", (char *)filetype_string, 1) == 0 ) || (strncmp("APPEND",(char *) filetype_string, 6) == 0 )) {
01223                     DOS_channel[channel].filetype = SEQUENTIAL;
01224 //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
01225                 } else {
01226                     /*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)*/
01227                     if (strncmp("S", (char *)filetype_string, 1)) {
01228                         DOS_channel[channel].filetype = SEQUENTIAL;
01229                     }
01230                     if (strncmp("R", (char *)filetype_string, 1)) {
01231                         DOS_channel[channel].filetype = RELATIVE;
01232                     }
01233                     if (strncmp("P", (char *)filetype_string, 1)) {
01234                         DOS_channel[channel].filetype = PROGRAM;
01235                     }
01236                     if (strncmp("U", (char *)filetype_string, 1) == 0 ) {
01237                         DOS_channel[channel].filetype = USER;
01238                     }
01239 //                    if (strncmp("L", filetype_string, 1))
01240 //                    {
01241 //                        DOS_channel[channel].filetype = USER;
01242 //                    }
01243 
01244 
01245                     /*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)*/
01246                     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*/
01247                         DOS_channel[channel].RW = RD_FILE;
01248                         file_status = D64SeekFile(filename_string, &track, &sector, &blocksize, &dirtrack, &dirsector, &direntry);    /*check if file is present or not*/
01249                         if (file_status == FILE_PRESENT) {
01250                             DOS_channel[channel].status = FILE_OPEN;    /*the file could be found*/
01251                             DOS_channel[channel].track = track;            /*save, the location of the first byte regarding this file on the "disk", to the appropriate registers*/
01252                             DOS_channel[channel].sector = sector;
01253                             DOS_channel[channel].buffer_pointer = 0;
01254                         } else {
01255                             DOS_channel[channel].status = NO_FILE;        /*the file could not be found*/
01256                             SetErrorCode(62,LED_ERROR);                    /*file not found*/
01257                         }
01258                     }
01259 
01260                     if ((strncmp("W", (char *)RW_string, 1) == 0 ) || (strncmp("WRITE",(char *) RW_string, 5) == 0 )) {
01261                         DOS_channel[channel].RW = WR_FILE;
01262                         file_status = D64SeekFile(filename_string, &track, &sector, &blocksize, &dirtrack, &dirsector, &direntry);    /*check if file is present or not*/
01263                         if (file_status == FILE_PRESENT) {
01264                             DOS_channel[channel].status = NO_FILE;        /*the file could not be found*/
01265                             SetErrorCode(63,LED_ERROR);                    /*file exists*/
01266                         } else {
01267                             DOS_channel[channel].status = FILE_OPEN;    /*the file could be found*/
01268 //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
01269 
01270                             DOS_channel[channel].track = track;            /*save, the location of the first byte regarding this file on the "disk", to the appropriate registers*/
01271                             DOS_channel[channel].sector = sector;
01272                             DOS_channel[channel].buffer_pointer = 0;
01273                         }
01274                     }
01275                     if ((strncmp("M", (char *)RW_string, 1) == 0 ) || (strncmp("MODIFY", (char *)RW_string, 6) == 0 )) {
01276                         DOS_channel[channel].RW = MODIFY_FILE;
01277 //to do: uitzoeken wat modify precies inhoud...
01278                     }
01279 
01280                 }
01281             }
01282 
01283             OutputToRS232();                        /*set standard output to RS232*/
01284             printf("\r\nOpen, channel %d", channel);    /*!!! DEBUG ONLY !!!*/
01285             printf("\r\n  channel_in_use:%03d",DOS_channel[channel].channel_in_use);
01286             printf("\r\n  next_action   :%03d",DOS_channel[channel].next_action);
01287             printf("\r\n  filename[0]   :%s",DOS_channel[channel].filename);
01288             printf("\r\n  filetype      :%03d",DOS_channel[channel].filetype);
01289             printf("\r\n  RW            :%03d",DOS_channel[channel].RW);
01290             printf("\r\n  track         :%03d",DOS_channel[channel].track);
01291             printf("\r\n  sector        :%03d",DOS_channel[channel].sector);
01292             printf("\r\n  buffer_pointer:%03d",DOS_channel[channel].buffer_pointer);
01293             printf("\r\n  used_buffer   :%03d",DOS_channel[channel].used_buffer);
01294             printf("\r\n  status        :%03d",DOS_channel[channel].status);
01295             printf("\r\n");                            /*!!! DEBUG ONLY !!!*/
01296             OutputToLCD();                            /*set standard output to LCD*/
01297             break;
01298         }
01299 
01300         case 15: {
01301             /*------------------------------------------------------*/
01302             /* Set LCD's contrast                                   */
01303             /* Syntax: "LCDCONTRAST=<value>"                        */
01304             /* Example: OPEN15,device,15,"LCDCONTRAST=ddd"<RETURN>  */
01305             /*          CLOSE 15<RETURN>                            */
01306             /*------------------------------------------------------*/
01307             if (strncmp("LCDCONTRAST=",(char *)command_string,12) == 0 ) {      /*check the beginning of the string)*/
01308                 SplitStringOn_Sign('=', command_string, value_string);
01309                 ValueFromString(value_string, &value_1);
01310                 if (value_1>0 && value_1<255) {
01311                     setting_contrast = value_1;                    /*copy new value to the correct register*/
01312                     // SetContrast();                                /*apply new setting*/
01313                     // SaveSettingsToEEPROM();                        /*save value to EEPROM*/
01314                     print_device_status("  CONTRAST... ");
01315                 } else {   /*incorrect value*/
01316                     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*/
01317                 }
01318                 DOS_channel[channel].channel_in_use = FALSE;    /*no further actions required*/
01319             }
01320 
01321             /*----------------------------------------------------------------*/
01322             /* 'N' = NEW - Format a floppy disk                               */
01323             /* Syntax: "NEW:<diskname>,<id>"                                  */
01324             /* Example: OPEN 15,8,15,"N:diskname,01"<RETURN>                  */
01325             /*          CLOSE 15<RETURN>                                      */
01326             /* <diskname> can be up to 16 characters                          */
01327             /* <id> can either be omitted or must be exactly 2 characters long*/
01328             /*----------------------------------------------------------------*/
01329             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)*/
01330                 if (file_type == D64_35T_MODE) {  //future or TODO: D64_35T_ER_MODE, D64_40T_MODE, D64_40T_ER_MODE
01331                     print_device_status(" FORMATTING.. ");
01332                     SplitStringOn_Sign(':', command_string, filename_string);
01333                     SplitStringOn_Sign(',', filename_string, value_string);
01334                     FormatD64File(filename_string, value_string);
01335                 } else {   /*creating a disk in the root directory is not supported*/
01336                     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*/
01337                 }
01338                 DOS_channel[channel].channel_in_use = FALSE;    /*no further actions required*/
01339             }
01340 
01341             /*----------------------------------------------------------------------------------------*/
01342             /* 'S' = SCRATCH (also referred to as 'delete')                                           */
01343             /* Syntax: "SCRATCH:<file>"                                                               */
01344             /* Example: OPEN 15,8,15,"S:filename"<RETURN>                                             */
01345             /*          CLOSE 15<RETURN>   (do not forget otherwise remaining commands may not work)  */
01346             /* You can use the wild cards '?' and '*' to delete several files at once.                */
01347             /*----------------------------------------------------------------------------------------*/
01348             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)*/
01349                 SplitStringOn_Sign(':', command_string, filename_string);
01350                 file_status = D64SeekFile(filename_string, &track, &sector, &blocksize, &dirtrack, &dirsector, &direntry);    /*check if file is present or not*/
01351                 if (file_status == FILE_PRESENT) {
01352                     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*/
01353                     SetErrorCode(0,LED_ON);                    /*unless we fail we will exit with no error*/
01354                     while (file_status == FILE_PRESENT) {     /*this function uses wildcards, so the same function needs to be repeated, keep checking untill false*/
01355                         print_device_status(" SCRATCHING.. ");
01356                         D64ScratchDirEntry(dirtrack, dirsector, direntry);
01357                         files_scratched++;
01358                         file_status = D64SeekFile(filename_string, &track, &sector, &blocksize, &dirtrack, &dirsector, &direntry);    /*check if file is present or not*/
01359                     }
01360                     SetErrorCode(1,LED_OFF);
01361                 } else {
01362                     SetErrorCode(62,LED_ERROR);                    /*file not found*/
01363                     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*/
01364                 }
01365                 DOS_channel[channel].channel_in_use = FALSE;    /*no further actions required*/
01366             }
01367 
01368             /*--------------------------------------------------*/
01369             /* 'R' = RENAME - Rename a file                     */
01370             /* Syntax: "RENAME:<newname>=<oldname>"             */
01371             /* Example:    OPEN 15,8,15,"R:newfilename=oldfilename"*/
01372             /*          CLOSE 15<RETURN>                        */
01373             /*--------------------------------------------------*/
01374             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)*/
01375                 SplitStringOn_Sign(':', command_string, filename_string);
01376                 SplitStringOn_Sign('=', filename_string, oldfilename_string);
01377                 file_status = D64SeekFile(oldfilename_string, &track, &sector, &blocksize, &dirtrack, &dirsector, &direntry);    /*check if file is present or not*/
01378                 if (file_status == FILE_PRESENT) {              /*although the '=0' has to be given in the command, we do not check for it*/
01379                     print_device_status("  RENAMING..  ");
01380                     SetErrorCode(0,LED_ON);                        /*unless we fail we will exit with no error*/
01381                     D64RenameDirEntry(filename_string, dirtrack, dirsector, direntry);
01382                     SetErrorCode(0,LED_OFF);                    /*we exit without error*/
01383                 } else {
01384                     SetErrorCode(62,LED_ERROR);                    /*file not found*/
01385                     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*/
01386                 }
01387                 DOS_channel[channel].channel_in_use = FALSE;    /*no further actions required*/
01388             }
01389 
01390 
01391             /*----------------------------------------*/
01392             /* INITIALIZE - re-read the BAM from disk */
01393             /* Abbreviation: I                        */
01394             /* Syntax: "INITIALIZE"                   */
01395             /*----------------------------------------*/
01396             /*Currently, this command is not supported            */
01397 
01398 
01399             /*----------------------------------------------------*/
01400             /* VALIDATE - Check and Fix Disk Consistency           */
01401             /* Abbreviation: V                                       */
01402             /* Syntax: "VALIDATE"                                  */
01403             /*----------------------------------------------------*/
01404             /*Currently, this command is not supported            */
01405             /*Validate will fix inconsistencies that can be caused by files that where opened but never closed. Beware: Validate also erases all random files! */
01406 
01407 
01408             /*-------------------------------------------------------*/
01409             /* 'C' = COPY - Create a copy of a file on the same disk */
01410             /* Syntax: "COPY:<destfile>=<sourcefile>" or "COPY:<destfile>=<sourcefile1>, <sourcefile2>, ..."*/
01411             /* If several source files are listed, than the destination file will contain the concatenated contents of all source files. */
01412             /*-------------------------------------------------------*/
01413             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)*/
01414                 SplitStringOn_Sign(':', command_string, filename_string);
01415                 SplitStringOn_Sign('=', filename_string, oldfilename_string);
01416                 file_status = D64SeekFile(oldfilename_string, &track, &sector, &blocksize, &dirtrack, &dirsector, &direntry);    /*check if file is present or not*/
01417                 if (file_status == FILE_PRESENT) {
01418                     print_device_status("  COPYING...  ");
01419                     CopyD64File(track, sector, blocksize);
01420                 } else {
01421                     SetErrorCode(62,LED_ERROR);                    /*file not found*/
01422                     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*/
01423                 }
01424                 DOS_channel[channel].channel_in_use = FALSE;    /*no further actions required*/
01425             }
01426 
01427             /*-------------------------------------------------------*/
01428             /* 'M-W' = memory write command                           */
01429             /* Syntax: OPEN 15,8,15,"M-W"CHR$(lowbyteaddr)CHR$(highbyteaddr)CHR$(numberofmemorylocations)CHR$(data)CHR$(data)CHR$(data):CLOSE 1<RETURN>    */
01430             /*-------------------------------------------------------*/
01431             if ((strncmp("M-W",(char *)command_string,3) == 0 )) {  // || (strncmp("M-W:", command_string, 4) == 0 ))        /*check the COMPLETE string*/
01432                 if ((command_string[3] == 119) && (command_string[4] == 0) && (command_string[5] == 2)) {
01433                     if ((command_string[6] - 32) == (command_string[7] - 64)) { /*check for new device address*/
01434                         devicenumber = command_string[7] - 64;            /*the new IEC device address of this device*/
01435                         print_device_status("  NEW DEVICE# ");
01436                         SetErrorCode(0,LED_ON);                            /*unless we fail we will exit with no error*/
01437                         print_D64_TSB(0,0,0,0);                            /*update display with the new device address*/
01438                         SetErrorCode(0,LED_OFF);                        /*we exit without error*/
01439                         DOS_channel[channel].channel_in_use = FALSE;    /*no further actions required*/
01440                     }
01441                 }
01442             }
01443 
01444             /*--------------------------------------------------------------------------------------------------------*/
01445             /* 'B-P' = buffer pointer command (i.o.w. Set the buffer pointer used by CHANNEL ??? to point to BYTE ??? */
01446             /* Syntax: OPEN 15,8,15,"B-P:";channel;byte:CLOSE 15<RETURN>                                              */
01447             /* Example: OPEN 15,8,15,"B-P:";5;2:CLOSE 15<RETURN>                                                      */
01448             /* Example: OPEN 15,8,15,"B-P";5;2:CLOSE 15<RETURN>                                                          */
01449             /* Example: OPEN 15,8,15,"B-P 5 2":CLOSE 15<RETURN>                                                          */
01450             /*--------------------------------------------------------------------------------------------------------*/
01451             if ((strncmp("B-P",(char *)command_string,3) == 0 )) {      /*check the string*/
01452                 string_pntr = 0;
01453                 string_pntr_2=ValueFromString(&command_string[string_pntr],&value_1);            /*search for the 1st number: channel*/
01454                 if (string_pntr_2!=FALSE) {
01455                     string_pntr = string_pntr + string_pntr_2;
01456                     string_pntr_2=ValueFromString(&command_string[string_pntr],&value_2);        /*search for the 2nd number: channel*/
01457                     if (string_pntr_2 != FALSE) {
01458                         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*/
01459                         OutputToRS232();                        /*set standard output to RS232*/
01460                         printf("\r\nB-P command, channel:%02d, BP:%03d",value_1,DOS_channel[DOS_channel[value_1].used_buffer].buffer_pointer);
01461                         OutputToLCD();                            /*set standard output to LCD*/
01462                     }
01463                 }
01464             }
01465 
01466 
01467             /*-------------------------------------------------------------------------*/
01468             /* 'B-R' = USER-command 1 (254 bytes, byte 0-1 are skipped)                */
01469             /* Syntax: OPEN 15,8,15,"B-R"channel;drive;track;sector":CLOSE 15<RETURN>  */
01470             /*-------------------------------------------------------------------------*/
01471             if ((strncmp("B-R",(char *)command_string,3) == 0 )) {      /*check the string*/
01472                 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*/
01473                 string_pntr_2=ValueFromString(&command_string[string_pntr],&value_1);                /*search for the 1st number: channel*/
01474                 if (string_pntr_2!=FALSE) {
01475                     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*/
01476                         string_pntr = string_pntr + string_pntr_2;
01477                         string_pntr_2=ValueFromString(&command_string[string_pntr],&value_2);            /*search for the 2nd number: channel*/
01478                         if (string_pntr_2 != FALSE) {
01479                             string_pntr = string_pntr + string_pntr_2;
01480                             string_pntr_2=ValueFromString(&command_string[string_pntr],&value_3);        /*search for the 2nd number: channel*/
01481                             if (string_pntr_2 != FALSE) {
01482                                 string_pntr = string_pntr + string_pntr_2;
01483                                 string_pntr_2=ValueFromString(&command_string[string_pntr],&value_4);    /*search for the 2nd number: channel*/
01484                                 if (string_pntr_2 != FALSE) {
01485                                     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*/
01486                                     DOS_channel[value_1].sector = value_4;                                /*save track and sector info*/
01487                                     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*/
01488 
01489                                     OutputToRS232();                        /*set standard output to RS232*/
01490                                     printf("\r\nB-R command, t:%03d, s:%03d",DOS_channel[value_1].track,DOS_channel[value_1].sector);
01491                                     OutputToLCD();                            /*set standard output to LCD*/
01492                                 }
01493                             }
01494                         }
01495                     }
01496                 }
01497             }
01498 
01499 
01500             /*-------------------------------------------------------------------------*/
01501             /* 'U1' or 'UA' = USER-command 1 (block read, 256 bytes)                   */
01502             /* Syntax: OPEN 15,8,15,"U1:"channel;drive;track;sector":CLOSE 15<RETURN>  */
01503             /* Example: OPEN 15,8,15,"U1:";5;0;18;1:CLOSE 15<RETURN>                   */
01504             /* Example: OPEN 15,8,15,"U1";5;0;18;1:CLOSE 15<RETURN>                       */
01505             /* Example: OPEN 15,8,15,"U1 5 0 18 1":CLOSE 15<RETURN>                       */
01506             /*-------------------------------------------------------------------------*/
01507             if (((strncmp("UA",(char *)command_string,2) == 0 )) || ((strncmp("U1",(char *)command_string,2) == 0 ))) {      /*check the string*/
01508                 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*/
01509                 string_pntr_2=ValueFromString(&command_string[string_pntr],&value_1);                /*search for the 1st number: channel*/
01510                 if (string_pntr_2!=FALSE) {
01511                     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*/
01512                         string_pntr = string_pntr + string_pntr_2;
01513                         string_pntr_2=ValueFromString(&command_string[string_pntr],&value_2);            /*search for the 2nd number: channel*/
01514                         if (string_pntr_2 != FALSE) {
01515                             string_pntr = string_pntr + string_pntr_2;
01516                             string_pntr_2=ValueFromString(&command_string[string_pntr],&value_3);        /*search for the 2nd number: channel*/
01517                             if (string_pntr_2 != FALSE) {
01518                                 string_pntr = string_pntr + string_pntr_2;
01519                                 string_pntr_2=ValueFromString(&command_string[string_pntr],&value_4);    /*search for the 2nd number: channel*/
01520                                 if (string_pntr_2 != FALSE) {
01521                                     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*/
01522                                     DOS_channel[value_1].sector = value_4;                                /*save track and sector info*/
01523                                     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*/
01524 
01525                                     OutputToRS232();                        /*set standard output to RS232*/
01526                                     printf("\r\nU1 command, t:%03d, s:%03d",DOS_channel[value_1].track,DOS_channel[value_1].sector);
01527                                     OutputToLCD();                            /*set standard output to LCD*/
01528                                 }
01529                             }
01530                         }
01531                     }
01532                 }
01533             }
01534 
01535 
01536             /*-------------------------------------------------------------------------*/
01537             /* 'B-W' = USER-command 2 (254 bytes block write)                               */
01538             /* Syntax: OPEN 15,8,15,"U2:"channel;drive;track;sector":CLOSE 15<RETURN>  */
01539             /*-------------------------------------------------------------------------*/
01540             if ((strncmp("B-W",(char *)command_string,3) == 0 )) {
01541                 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*/
01542                 string_pntr_2=ValueFromString(&command_string[string_pntr],&value_1);                /*search for the 1st number: channel*/
01543                 if (string_pntr_2!=FALSE) {
01544                     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*/
01545                         string_pntr = string_pntr + string_pntr_2;
01546                         string_pntr_2=ValueFromString(&command_string[string_pntr],&value_2);            /*search for the 2nd number: channel*/
01547                         if (string_pntr_2 != FALSE) {
01548                             string_pntr = string_pntr + string_pntr_2;
01549                             string_pntr_2=ValueFromString(&command_string[string_pntr],&value_3);        /*search for the 2nd number: channel*/
01550                             if (string_pntr_2 != FALSE) {
01551                                 string_pntr = string_pntr + string_pntr_2;
01552                                 string_pntr_2=ValueFromString(&command_string[string_pntr],&value_4);    /*search for the 2nd number: channel*/
01553                                 if (string_pntr_2 != FALSE) {
01554                                     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*/
01555                                     DOS_channel[value_1].sector = value_4;                                /*save track and sector info*/
01556                                     D64BlockWrite_new(DOS_channel[value_1].used_buffer,value_3,value_4);                                        /*write the desired block of the D64 image*/
01557 
01558                                     OutputToRS232();                        /*set standard output to RS232*/
01559                                     printf("\r\nB-W command, t:%03d, s:%03d",DOS_channel[value_1].track,DOS_channel[value_1].sector);
01560                                     OutputToLCD();                            /*set standard output to LCD*/
01561                                 }
01562                             }
01563                         }
01564                     }
01565                 }
01566             }
01567 
01568             /*-------------------------------------------------------------------------*/
01569             /* 'U2' or 'UB' = USER-command 2 (256 byte block write)                    */
01570             /* Syntax: OPEN 15,8,15,"U2:"channel;drive;track;sector":CLOSE 15<RETURN>  */
01571             /* Example: OPEN 15,8,15,"U2:";5;0;18;1:CLOSE 15<RETURN>                   */
01572             /* Example: OPEN 15,8,15,"U2";5;0;18;1:CLOSE 15<RETURN>                       */
01573             /* Example: OPEN 15,8,15,"U2 5 0 18 1":CLOSE 15<RETURN>                       */
01574             /*-------------------------------------------------------------------------*/
01575 
01576             if (((strncmp("U2",(char *)command_string,2) == 0 )) || ((strncmp("UB",(char *)command_string,2) == 0 ))) {      /*check the string*/
01577                 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*/
01578                 string_pntr_2=ValueFromString(&command_string[string_pntr],&value_1);                /*search for the 1st number: channel*/
01579                 if (string_pntr_2!=FALSE) {
01580                     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*/
01581                         string_pntr = string_pntr + string_pntr_2;
01582                         string_pntr_2=ValueFromString(&command_string[string_pntr],&value_2);            /*search for the 2nd number: channel*/
01583                         if (string_pntr_2 != FALSE) {
01584                             string_pntr = string_pntr + string_pntr_2;
01585                             string_pntr_2=ValueFromString(&command_string[string_pntr],&value_3);        /*search for the 2nd number: channel*/
01586                             if (string_pntr_2 != FALSE) {
01587                                 string_pntr = string_pntr + string_pntr_2;
01588                                 string_pntr_2=ValueFromString(&command_string[string_pntr],&value_4);    /*search for the 2nd number: channel*/
01589                                 if (string_pntr_2 != FALSE) {
01590                                     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*/
01591                                     DOS_channel[value_1].sector = value_4;                                /*save track and sector info*/
01592                                     D64BlockWrite_new(DOS_channel[value_1].used_buffer,value_3,value_4);                                        /*write the desired block of the D64 image*/
01593 
01594                                     OutputToRS232();                        /*set standard output to RS232*/
01595                                     printf("\r\nU2 command, t:%03d, s:%03d",DOS_channel[value_1].track,DOS_channel[value_1].sector);
01596                                     OutputToLCD();                            /*set standard output to LCD*/
01597                                 }
01598                             }
01599                         }
01600                     }
01601                 }
01602             }
01603 
01604 
01605             /*-------------------------------------------------------*/
01606             /* 'UI-' = USER-command speed up drive by 25%             */
01607             /* Syntax: OPEN 15,8,15,"UI-":CLOSE 1<RETURN>                 */
01608             /*-------------------------------------------------------*/
01609             if (strncmp("UI-",(char *)command_string,3) == 0 ) {      /*check the string*/
01610                 print_device_status("  VIC20-MODE  ");
01611                 SetErrorCode(0,LED_ON);                            /*unless we fail we will exit with no error*/
01612                 SetIEC_timings(TIMINGS_VIC20);                    /*set timings according the VIC-20 settings (25% faster mode)*/
01613                 VIC20_mode = TRUE;                                /*raise flag*/
01614                 // SaveSettingsToEEPROM();                            /*store new setting*/
01615                 SetErrorCode(0,LED_OFF);                        /*we exit without error*/
01616                 DOS_channel[channel].channel_in_use = FALSE;    /*no further actions required*/
01617             }
01618 
01619             /*-------------------------------------------------------*/
01620             /* 'UI+' = USER-command restore drive speed to normal     */
01621             /* Syntax: OPEN 15,8,15,"UI+":CLOSE 1<RETURN>                 */
01622             /*-------------------------------------------------------*/
01623             if (strncmp("UI+",(char *)command_string,3) == 0 ) {      /*check the string*/
01624                 print_device_status("   C64-MODE   ");
01625                 SetErrorCode(0,LED_ON);                            /*unless we fail we will exit with no error*/
01626                 SetIEC_timings(TIMINGS_DEFAULT);                /*set timings according the default settings (C64 compatible mode)*/
01627                 VIC20_mode = FALSE;                                /*raise flag*/
01628                 // SaveSettingsToEEPROM();                            /*store new setting*/
01629                 SetErrorCode(0,LED_OFF);                        /*we exit without error*/
01630                 DOS_channel[channel].channel_in_use = FALSE;    /*no further actions required*/
01631             }
01632 
01633             /*------------------------------*/
01634             /* In case none of the above... */
01635             /*------------------------------*/
01636             //to do:syntax error
01637             DOS_channel[channel].channel_in_use = FALSE;    /*no further actions required*/
01638 //            print_device_status("              ");                /*remove the 'action' message from the display*/
01639         }
01640     }
01641 }
01642 
01643 void DataHandler(void) {
01644 //    OutputToRS232();                        /*set standard output to RS232*/
01645 //    printf("\r\nDATAHANDLER");                /*!!! DEBUG ONLY !!!*/
01646 //    printf("\r\nData, channel %d",channel);    /*!!! DEBUG ONLY !!!*/
01647 //    printf("\r\ncmd_string:%s",command_string);    /*!!! DEBUG ONLY !!!*/
01648 //    printf("\r\nchannel:%d",channel);        /*!!! DEBUG ONLY !!!*/
01649 //    OutputToLCD();                            /*set standard output to LCD*/
01650 
01651     switch (channel) {                       /*-------------------------------------------*/
01652         case 0:                /* this channel is used for reading of files */
01653         {                    /*-------------------------------------------*/
01654             if ((DiskState == NO_CARD) || (DiskState == INVALID_POINTER)) {      /*escape sequence when no D64 is selected or no card is present*/
01655                 DOS_channel[channel].next_action = ABORT_SENDING;
01656             }
01657 
01658             switch (DOS_channel[channel].next_action) {
01659                 case ABORT_SENDING: {          /*file not found situation*/
01660                     SetErrorCode(62,LED_ERROR);                /*file not found*/
01661                     IEC_turnaround();        /*we now SEND data to the bus so... make our device a talker*/
01662                     FreeIEC();                /*BUT... since there's nothing to send, free the bus and the computer will detect this as an valid error situation*/
01663                     break;
01664                 }
01665 
01666                 case CARD_DIRECTORY: {
01667                     print_device_status("  LOADING...  ");
01668                     CardDirectory();                        /*send the MMC/SD_card Directory information*/
01669                     print_device_status("             ");
01670                     break;
01671                 }
01672 
01673                 case DIRECTORY: {
01674                     print_device_status(" LOADING DIR. ");
01675                     D64Directory();                        /*send ImageDirectory information of the selected drive*/
01676                     print_device_status("              ");
01677                     break;
01678                 }
01679 
01680                 case RD_FILE_FROM_ROOT: {
01681                     if (file_status != FALSE) {
01682                         print_device_status("  LOADING...  ");
01683                         OutputToRS232();
01684                         printf("%s",command_string);        /*print filename on first line of LCD*/
01685                         OutputToLCD();
01686                         LoadFileFromCard(&file);
01687                         print_device_status("              ");
01688                     } else {
01689                         SetErrorCode(62,LED_ERROR);                /*file not found*/
01690                         IEC_turnaround();        /*we now SEND data to the bus so... make our device a talker*/
01691                         FreeIEC();                /*BUT... since there's nothing to send, free the bus and the computer will detect this as an valid error situation*/
01692                         DOS_channel[channel].next_action = ABORT_SENDING;
01693                     }
01694                     break;
01695                 }
01696 
01697                 case RD_FILE: {
01698                     if (file_status == FILE_PRESENT) {
01699                         print_device_status("  LOADING...  ");
01700                         OutputToRS232();
01701                         printf("%s",command_string);            /*print filename to LCD*/
01702                         OutputToLCD();
01703                         LoadD64File(track, sector, blocksize);     /*load the actual file from the D64-file*/
01704                         print_device_status("              ");
01705                     } else {
01706                         SetErrorCode(62,LED_ERROR);                /*file not found*/
01707                         IEC_turnaround();        /*we now SEND data to the bus so... make our device a talker*/
01708                         FreeIEC();                /*BUT... since there's nothing to send, free the bus and the computer will detect this as an valid error situation*/
01709                         DOS_channel[channel].next_action = ABORT_SENDING;
01710                         print_device_status("              ");
01711                     }
01712                     break;
01713                 }
01714             }
01715             break;
01716         }
01717 
01718         /*-------------------------------------------*/
01719         case 1:                /* this channel is used for writing of files */
01720         {                    /*-------------------------------------------*/
01721             if ((DiskState == NO_CARD) || (DiskState == INVALID_POINTER))        /*escape sequence when no D64 is selected or no card is present*/
01722                 DOS_channel[channel].next_action = ABORT_RECEIVING;
01723 
01724             switch (DOS_channel[channel].next_action) {
01725                 case ABORT_RECEIVING: {      /*file not found situation*/
01726                     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...)*/
01727                     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*/
01728                     break;
01729                 }
01730 
01731                 case WR_FILE_TO_ROOT: {
01732                     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...)*/
01733                     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*/
01734                     DOS_channel[channel].next_action = ABORT_RECEIVING;
01735                     break;
01736                 }
01737 
01738                 case WR_FILE: {
01739                     if (file_status == FILE_NOT_PRESENT) {
01740                         print_device_status("   SAVING...  ");
01741                         OutputToRS232();
01742                         printf("%s",command_string);            /*print filename on first line of LCD*/
01743                         OutputToLCD();
01744                         SaveD64File();                            /*save the actual file to the D64-file*/
01745                         print_device_status("              ");
01746                     } else {
01747                         SetErrorCode(63,LED_ERROR);                /*file exists*/
01748                         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*/
01749                         DOS_channel[channel].next_action = ABORT_RECEIVING;
01750                     }
01751                     break;
01752                 }
01753 
01754                 case REPLACE_FILE: {
01755                     if (file_status == FILE_PRESENT) {
01756                         print_device_status("  REPLACING.. ");
01757                         D64ScratchDirEntry(dirtrack, dirsector, direntry);    /*remove entry*/
01758                         files_scratched = 1;
01759                         strcpy((char *)command_string,(char *) filename_string);            /*make sure the save routine uses the correct data, the command without the @0:*/
01760                         SaveD64File();                                        /*save the actual file to the D64-file*/
01761                         print_device_status("              ");
01762                     }
01763                     break;
01764                 }
01765             }
01766             break;
01767         }
01768 
01769         case 2:;        /*these channels are used for...*/
01770         case 3:
01771             ;
01772         case 4:
01773             ;
01774         case 5:
01775             ;
01776         case 6:
01777             ;
01778         case 7:
01779             ;
01780         case 8:
01781             ;
01782         case 9:
01783             ;
01784         case 10:
01785             ;
01786         case 11:
01787             ;
01788         case 12:
01789             ;
01790         case 13:
01791             ;
01792         case 14: {
01793             if (IEC_state == ACTIVE_TALK) {  /*if the drive is expected to TALK... speak now*/
01794                 EOI = FALSE;
01795                 LED_GREEN = 1;                            /*drive LED-ON*/
01796                 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)*/
01797                 IEC_turnaround();                        /*we now SEND data to the bus so... make our device a talker*/
01798                 while (IEC_ATN() == 1) {                     /* the listener (computer) indicates (by making ATN=0) it requires no more data (for now)*/
01799                     if (command_string[0] == '#') {                      /*if the user's/computer's last command specified opening a buffer, then handle accordingly...*/
01800                         command_string[0] = 0;                            /*make sure the command string is discarded to prevent looping*/
01801                         IEC_send(DOS_channel[channel].used_buffer);        /*send the buffer number of the just opened buffer*/
01802                     } else {
01803 //                        if (DOS_channel[channel].buffer_pointer == 255)        /*when the last byte is going to been send*/
01804 //                        {
01805 //                            EOI = TRUE;                                        /*indicate that this is the last byte of the buffer*/
01806 //                        }
01807                         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*/
01808                         DOS_channel[channel].buffer_pointer++;                /*increment buffer pointer by one*/
01809                     }
01810                     /*wait for the listener (computer) to release the data-line (ready to receive data), this may take forever... (according the IEC-bus definition)*/
01811                     while (IEC_DATA() == 0);            /*data is released when new data can be handled by the listener (the computer at this stage)*/
01812                     /*OR*/
01813                     /*data is released when ATN goes low because NO MORE data is required*/
01814                 }
01815                 IEC_undoturnaround();
01816                 enable_ATN_interrupt();                            /*all is back to normal, enable interrupts on ATN line*/
01817                 SetErrorCode(0,LED_OFF);                        /*error-code is 0, LED is OFF*/
01818             }
01819 
01820             if (IEC_state == ACTIVE_LISTEN) {  /*if the drive is expected to listen then... we're all ear*/
01821                 OutputToRS232();    /*set standard output to RS232*/
01822                 printf("\r\ntp10 active listen");    /*!!! DEBUG ONLY !!!*/
01823                 OutputToLCD();        /*set standard output to LCD*/
01824             }
01825 
01826             break;
01827         }
01828 
01829         /*---------------------------------------*/
01830         case 15:                /* this channel is used for DOS-commands */
01831         {                        /*---------------------------------------*/
01832             if (IEC_state == ACTIVE_TALK)
01833 //            if ((IEC_state == ACTIVE_TALK) && (DOS_channel[15].channel_in_use == TRUE))
01834             {
01835                 /*-------------------------------------------------------*/
01836                 /* Reading the error channel is a special situation      */
01837                 /* Example: OPEN 15,8,15<RETURN>                         */
01838                 /*          INPUT#15, A, B$, C, D<RETURN>                */
01839                 /*          CLOSE 15<RETURN>                             */
01840                 /*-------------------------------------------------------*/
01841                 SendErrorMessage();            /*this is handled immediately*/
01842             } else {
01843                 DOS_channel[channel].channel_in_use = TRUE;        /*claim this channel*/
01844                 WaitForString(command_string, TRUE);            /*wait for an operator string that ends with an EOI*/
01845             }
01846 
01847             break;
01848         }
01849     }
01850 }
01851 
01852 /*****************************************************************************************************************/
01853 /*The following routine will check for the PCB type by testing for the capacitor value on port RA0*/
01854 /*During this testing procedure no buttons may be pressed*/
01855 void AutoDetectPcbType(void) {
01856 
01857     PCB_type = v1_1;                                            /*typical timer value: 10771 - 10835*/
01858 }
01859 
01860 void NoCardMenu(void) {
01861     // Lcd_XY_address(0,0);
01862     putch('o');
01863 //   Lcd_XY_address(0,2);
01864     putch(0x16);
01865 //   Lcd_XY_address(0,4);
01866     putch('i');
01867     while (ReadButtons()) {
01868         if    (button_prev == TRUE)                        /*decrease contrast (lighter)*/
01869         {                                                /*---------------------------*/
01870             setting_contrast--;
01871             if (setting_contrast < 0x81) {
01872                 setting_contrast = 0x81;                /*lower limit*/
01873                 //             Lcd_XY_address(0,1);
01874                 printf(" Min. reached ");
01875                 DelayBigMs(350);
01876             } else {
01877 //                SetContrast();                            /*apply new setting*/
01878                 //           Lcd_XY_address(0,1);
01879                 //         Lcd_ProgressBar((0xff-setting_contrast), 0x81);
01880                 //       SaveSettingsToEEPROM();                    /*save value to EEPROM*/
01881                 DelayBigMs(200);
01882             }
01883             OutputToRS232();                            /*set standard output to RS232*/
01884             printf("\r\nLCD-Lighter, contrast =%02x",setting_contrast);
01885             OutputToLCD();                                /*set standard output to LCD*/
01886         }
01887 
01888         if    (button_select == TRUE)                        /*increase contrast (darker)*/
01889         {                                                /*--------------------------*/
01890             setting_contrast++;
01891             if (setting_contrast > 0xFE) {
01892                 setting_contrast = 0xFE;                /*upper limit*/
01893                 //     Lcd_XY_address(0,1);
01894                 printf(" Max. reached ");
01895                 DelayBigMs(350);
01896             } else {
01897                 //             SetContrast();                            /*apply new setting*/
01898                 //   Lcd_XY_address(0,1);
01899                 // Lcd_ProgressBar((0xff-setting_contrast), 0x81);
01900                 //  SaveSettingsToEEPROM();                    /*save value to EEPROM*/
01901                 DelayBigMs(200);
01902             }
01903             OutputToRS232();                            /*set standard output to RS232*/
01904             printf("\r\nLCD-Darker, contrast =%02x",setting_contrast);
01905             OutputToLCD();                                /*set standard output to LCD*/
01906         }
01907 
01908         if    (button_next == TRUE) {                      /*info button*/
01909             OutputToRS232();                            /*set standard output to RS232*/
01910             printf("\r\nInfo button pressed");
01911             OutputToLCD();                                /*set standard output to LCD*/
01912             //     Lcd_clr();
01913             HardWareTestMenu();
01914             //   Lcd_clr();
01915             break;
01916         }
01917     }
01918 }
01919 
01920 void HardWareTestMenu(void) {
01921 //   Lcd_clr();
01922 //   Lcd_XY_address(0,0);
01923     printf("LED test");
01924 //   Lcd_XY_address(0,2);
01925     printf("IO & settings");
01926 //    Lcd_XY_address(0,4);
01927     printf("Exit");
01928     DelayBigMs(1000);
01929     while (1) {
01930         ReadButtons();
01931         if    (button_prev == TRUE)                        /*LED-test routines*/
01932         {                                                /*-----------------*/
01933             //          Lcd_clr();
01934             //        Lcd_XY_address(5,2);
01935             printf("OFF");
01936             LED_GREEN = 0;
01937             LED_RED = 0;
01938             DelayBigMs(2000);
01939             //      Lcd_XY_address(4,2);
01940             printf("green");
01941             LED_GREEN = 1;
01942             LED_RED = 0;
01943             DelayBigMs(2000);
01944             //    Lcd_XY_address(4,2);
01945             printf(" red ");
01946             LED_GREEN = 0;
01947             LED_RED = 1;
01948             DelayBigMs(2000);
01949             //  Lcd_XY_address(3,2);
01950             printf("red+green");
01951             LED_GREEN = 1;
01952             LED_RED = 1;
01953             DelayBigMs(2000);
01954             LED_GREEN = 0;
01955             LED_RED = 0;
01956             break;
01957         }
01958 
01959         if    (button_select == TRUE)                        /*IO & settings*/
01960         {                                                /*-------------*/
01961 
01962             //        Lcd_XY_address(0,4);
01963             printf("Contrast:%02X",setting_contrast);
01964             //        Lcd_XY_address(0,5);
01965             printf("PCBtimer:%05d",PCB_type_timer);
01966 
01967             DelayBigMs(3000);
01968             break;
01969         }
01970 
01971         if    (button_next == TRUE)                        /*Exit-button*/
01972         {                                                 /*-----------*/
01973             break;
01974         }
01975     }
01976 }
01977 
01978 
01979 /*this routine wait for a card to be inserted, once inserted it will be initialised, when all is OK this routine will exit*/
01980 unsigned char CardStatus(void) {
01981     unsigned char err_code;
01982 
01983     if (CARD_DETECT == 1) {
01984         //     Lcd_XY_address(4,1);
01985         //    Lcd_CharBold();
01986         printf("INSERT");
01987         //     Lcd_XY_address(5,3);
01988         printf("CARD");
01989         //     Lcd_CharNormal();
01990         //     Lcd_XY_address(0,5);
01991         printf("  (20%02d%02d%02d)",RELEASE_VERSION,RELEASE_VERSION_SUB,RELEASE_VERSION_SUB_SUB);
01992         DiskState = NO_CARD;
01993         return(FALSE);
01994     }
01995 
01996     //  Lcd_clr();
01997 //   Lcd_XY_address(0,0);
01998     printf("Card detected ");
01999 
02000     //if(WR_PROTECT == 1)                        /*check if the SD-cards write protect "switch" has been set*/
02001     //{
02002     //    Lcd_XY_address(0,1);
02003     //    printf("Card wr. prot.");
02004     //    DiskState = NO_CARD;
02005     //    return(FALSE);
02006     //}
02007 
02008     DelayMs(250);                                    /*do not access card immediatly, wait for card to stabelise*/
02009 //    Lcd_XY_address(0,1);
02010     printf("Init. card:   ");
02011 //    Lcd_XY_address(0,2);                        /*set cursor to next line to print error messages*/
02012     if (Init_Card_SPI()) {
02013         DelayMs(100);                                /*do not access card immediatly...*/
02014         err_code = FindDrive();
02015         if (err_code != TRUE) {
02016             //          Lcd_XY_address(0,3);
02017             switch (err_code) {
02018                 case ERROR_ATAREAD_CMD17: {
02019                     printf("ATA:err. CMD17");        /*CMD17 does not respond, the command is not accepted...*/
02020                     break;
02021                 }
02022 
02023                 case ERROR_ATAREAD_TIMEOUT: {
02024                     printf("ATA:rd timeout");        /*timeout on waiting for start of data transfer*/
02025                     break;
02026                 }
02027 
02028                 case ERROR_FAT_READBOOTSECTOR: {
02029                     printf("FAT:read boots");
02030                     break;
02031                 }
02032 
02033                 case ERROR_FAT_JUMPOPCODE: {
02034                     printf("FAT:jump opcode");
02035                     break;
02036                 }
02037 
02038                 case ERROR_FAT_BLOCKSIZE: {
02039                     printf("FAT:blocksize  ");
02040                     break;
02041                 }
02042 
02043                 case ERROR_FAT_MEDIUM: {
02044                     printf("FAT:wr. medium ");
02045                     break;
02046                 }
02047 
02048                 default: {
02049                     printf("Undefined.....");
02050                     break;
02051                 }
02052             }
02053             //        Lcd_XY_address(0,4);
02054             printf("Card not supp.");
02055         } else {
02056             //      Lcd_XY_address(11,1);
02057             printf("OK");
02058             DiskState = CARD_ACTIVE;
02059             return(TRUE);
02060         }
02061     }
02062     DelayMs(100);                        /*when initialise failed wait before retry, otherwise the error message could not be read*/
02063     DiskState = NO_CARD;
02064     return(FALSE);
02065 }
02066 
02067 
02068 /*initialise MMC/SD-card in SPI-mode*/
02069 unsigned char Init_Card_SPI(void) {
02070     if (CARD_Init() == FALSE);                    /*The official initialisation routines as described in most of the documentation*/
02071     {                                            /*If the official init fails, try the alternative init*/
02072         if (CARD_AlternativeInit() == FALSE) {  /*The alternative init, required ONLY because SanDisk does not follow the world's standards... <zucht>*/
02073             return(FALSE);
02074         }
02075     }
02076 
02077   //  Card_CID();                                    /*request Card - ID*/
02078   //  Card_CSD();                                    /*request Card Specific Data*/
02079 
02080     if (CARD_OperatingConditions(Response_data) == FALSE) {
02081         printf("CARD:err CMD58");
02082         return(FALSE);
02083     } else {
02084         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*/
02085             printf("CARD:voltage  ");
02086             return(FALSE);
02087         }
02088 
02089         printf("CARD:OK       ");
02090         return(TRUE);
02091     }
02092 }
02093 
02094 /*This routine will count ALL files within the current directory (which could be root or subdirectory)*/
02095 void CountFiles(void) {
02096     print_device_status("COUNTING FILES");    /*inform the user about a possible time consuming task*/
02097 
02098     if (FileSearch(&file,0)) {              /*search for the first file on the card*/
02099         CountedFiles = 1;
02100         while (FileSearch(&file,1)) {          /*goto the next file*/
02101             /*count ALL files (even the irrelevant files, since they do occupy diskspace, max 512 files in root you know)*/
02102             CountedFiles++;                    /*increment file-counter*/
02103         }
02104         FileSearch(&file,0);                /*set the search routines back to the first file*/
02105     } else {
02106         CountedFiles = 0;
02107     }
02108 
02109     //  OutputToRS232();                                /*set standard output to RS232*/
02110     printf("\r\nNumber of files in current (sub)dir: %d",CountedFiles);
02111     //  OutputToLCD();                                    /*set standard output to LCD*/
02112 }
02113 
02114 /*This routine will 'filter' the currently 'selected' file,*/
02115 /*when the file does not meet the expected standards it returns 'FALSE'*/
02116 unsigned char FileFilter(void) {
02117     /* Disk type                 | Size   */
02118     /* --------------------------+--------*/
02119     /* 35 track, no errors       | 174848 */
02120     /* 35 track, 683 error bytes | 175531 */
02121     /* 40 track, no errors       | 196608 */
02122     /* 40 track, 768 error bytes | 197376 */
02123 
02124     if ((file.name[8] == 'P') && (file.name[9] == 'R') && (file.name[10] == 'G')) {
02125         return(PRG_FILE);
02126     }
02127 
02128     if ((file.name[8] == 'D') && (file.name[9] == '6') && (file.name[10] == '4')) {
02129         if (file.size == 174848)
02130             return(D64_35T_MODE);
02131 
02132         if  (file.size == 175531)
02133             return(D64_35T_ER_MODE);
02134 
02135         if (file.size == 196608)
02136             return(D64_40T_MODE);
02137 
02138         if (file.size == 177376)
02139             return(D64_40T_ER_MODE);
02140     }
02141 
02142 //    if((file.name[8] == 'T') && (file.name[9] == '6') && (file.name[10] == '4'))
02143 //    {
02144 //        return(T64_MODE);
02145 //    }
02146 
02147     if ((file.size == 0) && (file.cluster!=0))
02148         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*/
02149 
02150     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] == ' '))
02151         return(SUBDIRECTORY);    /*this subdirectory points to the current directory*/
02152 
02153     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] == ' '))
02154         return(SUBDIRECTORY);    /*this subdirectory points to the parent directory (which could be root)*/
02155 
02156     if ((file.name[0] != 0x20) && (file.name[8] == 0x20) && (file.name[9] == 0x20) && (file.name[10] == 0x20))
02157         return(UNKNOWN);        /*when a filename has no extension, show it simply because it could be a file belonging to an IDE64 fixed game*/
02158 
02159     return(FALSE);
02160 }
02161 
02162 /*this routine will search for the next available buffer, when no buffer can be found it responds with 255*/
02163 unsigned char SearchFreeBuffer(void) {
02164     unsigned char lp;
02165 
02166     lp=0;
02167     while (lp<MAX_NUMBER_OF_DOS_BUFFERS) {
02168         if (DOS_buffer[lp].buffer_in_use == FALSE) {  /*TRUE means that this channel is in use, FALSE means it is available*/
02169             return(lp);                                /*return with the number of the available channel*/
02170         }
02171         lp++;
02172     }
02173     return(255);                                    /*an error has occurred, there are no free channels left*/
02174 }
02175 
02176 /*****************************************************************************************************************/
02177 
02178 /*this routine will wait untill a string has been loaded that is terminated by an EOI*/
02179 void WaitForString(unsigned char *outputstring, unsigned frame_handshake) {
02180     unsigned char cnt;
02181 
02182     TimeOut = FALSE;
02183     EOI = FALSE;
02184     cnt = 0;
02185     while ((TimeOut == FALSE) && (EOI == FALSE)) {             /*get filename/instruction, this is all data untill an EOI is received*/
02186         outputstring[cnt] = IEC_receive(frame_handshake);    /*save the received char to a string specified by the caller of this routine*/
02187 // printf("%02x", outputstring[cnt]);                        /*print string to be captured for debug purposes...*/
02188         cnt++;
02189     }
02190     outputstring[cnt] = 0;    /*close the string with a "nul"*/
02191 }
02192 
02193 
02194 /*This routine will search for the first 'number' and puts this number into a register*/
02195 /*it returns 0 (FALSE) when the number does not fit into an unsigned char*/
02196 /*it returns the position of the character AFTER the number. so that this can be used for the next number search...*/
02197 unsigned char ValueFromString(unsigned char *inputstring, unsigned char *outputvalue) {
02198     unsigned char lp;
02199 
02200     lp = 0;
02201     *outputvalue = 0;
02202 
02203     while ((inputstring[lp] < '0') || (inputstring[lp] > '9')) {  /*check if this character is not a number*/
02204         lp++;                        /*keep looping until a number is found*/
02205         if (inputstring[lp] == 0) {  /*when the end of the string has been reached, exit false*/
02206             return(FALSE);            /*if there were no numbers at the beginning of this string, return FALSE*/
02207         }
02208     }
02209 
02210     while ((inputstring[lp] >= '0') && (inputstring[lp] <= '9')) {  /*check if this character is a number*/
02211         if (*outputvalue > 25) {
02212             return(FALSE);    /*the number in the string is larger the 255 and is not a 'unsigned char' exit routine*/
02213         } else {
02214             *outputvalue = *outputvalue * 10;
02215             *outputvalue = *outputvalue + (inputstring[lp] - '0');
02216             lp++;
02217         }
02218     }
02219 
02220     return(lp);        /*the first position directly after the number*/
02221 }
02222 
02223 
02224 /*This routine will search for the first 'number' and puts this number into a register*/
02225 /*the number has to start a the first character otherwise it returns false*/
02226 unsigned char LongValueFromString(unsigned char *inputstring, unsigned long *outputvalue) {
02227     unsigned char lp;
02228 
02229     lp = 0;
02230     *outputvalue = 0;
02231 
02232     while ((inputstring[lp] >= '0') && (inputstring[lp] <= '9')) {  /*check if this character is a number*/
02233         *outputvalue = *outputvalue * 10;
02234         *outputvalue = *outputvalue + (inputstring[lp] - '0');
02235         lp++;
02236     }
02237 
02238     return(lp);        /*the first position directly after the number*/
02239 }
02240 
02241 
02242 /*this routine extract the filename from the command string, it will remove all unwanted options and leaves the filename only    */
02243 /*Some of the possible entries to indicate the problem to be solved by this routine:                                            */
02244 /*normal open    : commandstring = "0:filename,s,r"                                                                                */
02245 /*simplified open: commandstring = "filename,s,r"                                                                                */
02246 /*simplified open: commandstring = "filename"                                                                                    */
02247 /*simplified open: commandstring = "0:filename"                                                                                    */
02248 /*replacement    : commandstring = "@0:filename,s,r"                                                                            */
02249 /*copy           : commandstring = "C0:backup=original"                                                                            */
02250 /*multiple copy  : commandstring = "COPY0:<destfile>=<sourcefile>" or "COPY:<destfile>=<sourcefile1>, <sourcefile2>, ..."        */
02251 /*therefore we may conclude that everything AFTER ':' and BEFORE ',' (or end-of-string) is the filename                            */
02252 void ExtractFilenameFromString(unsigned char *input_string, unsigned char *output_string) {
02253     unsigned char tempstring[41];
02254 
02255     strcpy((char *)tempstring, (char *)input_string); /*this is required because the splitstring_on function destroys the inputvalues*/
02256     if (!SplitStringOn_Sign(':', tempstring, output_string))    /*remove all characters BEFORE the ':'-sign*/
02257     {                                                            /*if this succeeds the ':'-sign was found we can continue 'stripping' the string*/
02258         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*/
02259     }
02260     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*/
02261 }
02262 
02263 
02264 
02265 /*this routine will strip all characters before the given sign*/
02266 /*it will return the characters BEFORE the first sign in BEFORE_STRING (sign is not included in the result)*/
02267 /*it will return the characters AFTER the first sign in AFTER_STRING (sign is not included in the result)*/
02268 unsigned char SplitStringOn_Sign(unsigned char sign, unsigned char *beforesign_string, unsigned char *aftersign_string) {
02269     unsigned char lp, lp2;
02270 
02271     lp = 0;
02272     while (beforesign_string[lp]) {
02273         if (beforesign_string[lp] == sign) {
02274             lp++;
02275             lp2 = 0;
02276             while (beforesign_string[lp+lp2]) {
02277                 aftersign_string[lp2] = beforesign_string[lp+lp2];
02278                 lp2++;
02279             }
02280             beforesign_string[--lp] = 0;                            /*terminate the command_string, the :-sign is not included any more in te string*/
02281             aftersign_string[lp2] = 0;                                /*terminate the copied string*/
02282             return(TRUE);                                            /*indicate that the conversion (removal of all chars before :-sign) has succeeded*/
02283         }
02284         lp++;
02285     }
02286     return(FALSE);                                                    /*indicate that the conversion (removal of all chars before :-sign) has failed*/
02287 }
02288 
02289 
02290 /*****************************************************************************************************************/
02291 
02292 /*this routine print some prefedined text to the display AND serial port*/
02293 void print_device_status(const unsigned char *message) {
02294 //    Lcd_XY_address(0,2);
02295 //    Lcd_CharBold();
02296     printf("%s",message);
02297 //    Lcd_CharNormal();
02298 
02299     OutputToRS232();                    /*set standard output to RS232*/
02300     printf("\r\n%s",message);
02301     OutputToLCD();                        /*set standard output to LCD*/
02302 }
02303 
02304 /*this routine print the name of the current file (which is suppost to be a D64 file)*/
02305 void print_D64_name(unsigned char mode) {
02306     unsigned char i;
02307 
02308     if (mode == INVERTED)                            /*depending on requested mode print in normal or inverse-mode*/
02309 //        Lcd_CharInvert();
02310 
02311 //    Lcd_XY_address(0,0);
02312         printf("%05d in dir. ",CountedFiles);            /*show the total number of files (sub)directory*/
02313 //    Lcd_XY_address(0,1);                            /*set cursor to line we want to use*/
02314 
02315     if (file_type == NONE) {
02316         printf("%05d=        ",file_number);        /*show the current selection and clear the line*/
02317 //        Lcd_XY_address(6,1);                        /*set cursor back...*/
02318     } else {
02319         printf("%05d=        ",file_number);        /*show the current selection and clear the line*/
02320 //        Lcd_XY_address(6,1);                        /*set cursor back...*/
02321         for (i=0; i<8; i++)                         /*print selection (or currently selected) 8.3-filename*/
02322             putch(file.name[i]);                    /*character after character*/
02323 
02324         OutputToRS232();                            /*output the same info to the serial port also*/
02325         printf("\r\nfilename:");
02326         for (i=0; i<8; i++)                         /*print selection (or currently selected) 8.3-filename*/
02327             putch(file.name[i]);                    /*character after character*/
02328         OutputToLCD();                                /*set standard output to LCD*/
02329     }
02330 
02331 //    Lcd_CharNormal();
02332 //    Lcd_XY_address(0,5);
02333     printf("%c=%02d ",0x0d,devicenumber);            /*print the device number on the display*/
02334     if (file_type == NONE)                           /*indicate on the display we are working in the root-dir of the card (HD-mode*/
02335         printf("Hard-disk");
02336     if (file_type == SUBDIRECTORY)                   /*indicate on the display we are working in the root-dir of the card (HD-mode*/
02337         printf("Hard-disk");
02338     if (file_type == PRG_FILE)                       /*...*/
02339         printf("PRG-file ");
02340     if (file_type == UNKNOWN)                       /*...*/
02341         printf("-UNKNOWN-");
02342     if (file_type == D64_35T_MODE)                   /*indicate on the display the D64 file 35 tracks no errors*/
02343         printf(".D64 35T ");
02344     if (file_type == D64_35T_ER_MODE)               /*indicate on the display the D64 file 35 tracks with errors*/
02345         printf(".D64 35Te");
02346     if (file_type == D64_40T_MODE)                   /*indicate on the display the D64 file 40 tracks no errors*/
02347         printf(".D64 40T ");
02348     if (file_type == D64_40T_ER_MODE)               /*indicate on the display the D64 file 40 tracks with errors*/
02349         printf(".D64 40Te");
02350     if (file_type == T64_MODE)                       /*indicate on the display the T64*/
02351         printf(".T64-mode");
02352 }
02353 
02354 /*this routine prints Track Sector and (remaining/loaded) blocks*/
02355 void print_D64_TSB(unsigned char trk, unsigned char sec, unsigned int blk, unsigned int total_blk) {
02356     static unsigned char previous_track;
02357     unsigned int blockcounter;
02358 
02359     blockcounter = total_blk - blk;                                    /*calculate the current block*/
02360 
02361     //  Lcd_XY_address(0,3);                                            /*set the LCD coordinates*/
02362 //   Lcd_ProgressBar(blk, total_blk);                                /*draw a progress bar*/
02363 //   Lcd_XY_address(0,4);                                            /*set the LCD coordinates*/
02364     printf("%c=%02d T=%02d S=%02d",0x0e,error_code,trk,sec);        /*show the error code, track and sector*/
02365 
02366     OutputToRS232();                                                /*output the same info to the serial port also*/
02367     printf("\r\n%02d,%02d,%d/%d",trk,sec,blockcounter,total_blk);    /*send to serial the Track and sector info*/
02368     OutputToLCD();                                                    /*set standard output to LCD*/
02369 
02370     //Sound_TrackChange(trk-previous_track);                            /*play a sound (if required) of a moving head*/
02371     previous_track = trk;                                            /*keep track of the number of tracks we move within the disk, this in order to simulate the sound properly*/
02372 }
02373 
02374 
02375 
02376 /*this routine is to be used to select a D64 image from the inserted card*/
02377 void SelectD64Image(void) {
02378     unsigned char filefilter_result;
02379     unsigned char blink_loop;
02380 
02381     ReadButtons();
02382     if    (button_prev == TRUE) {
02383         if (file_number == 1) {
02384             file_number=0;                                /*file counter is now '0' which means 'ROOT directory'*/
02385             file_type = NONE;                            /*and because the user has selected root, the selected file_type = NONE*/
02386         } else {
02387             if (file_number > 1) {
02388                 if (FileSearch(&file,2)) {              /*goto the previous D64 file*/
02389                     file_number--;                        /*decrease selected file counter*/
02390                 }
02391                 filefilter_result = FileFilter();        /*check the selected file*/
02392                 file_type = filefilter_result;
02393             }
02394         }
02395         DiskState = INVALID_POINTER;
02396         //     Lcd_XY_address(0,3);
02397         //    Lcd_SelectionBar((CountedFiles-file_number), CountedFiles);
02398         print_D64_name(INVERTED);                        /*write the selection to display in inverted mode*/
02399         DelayBigMs(BUTTON_SELECTION_RATE);                /*delay determines selection repetition rate*/
02400     }
02401 
02402     if    (button_next == TRUE) {
02403         if (file_number < CountedFiles) {
02404             if (file_number == 0)                        /*the first file on the card needs no search since it is allready found*/
02405                 file_number++;                            /*increase selected file counter*/
02406             else if (FileSearch(&file,1))               /*goto the next D64 file*/
02407                 file_number++;                        /*increase selected file counter*/
02408         }
02409         filefilter_result = FileFilter();                /*check the selected file*/
02410         file_type = filefilter_result;
02411         DiskState = INVALID_POINTER;
02412         //     Lcd_XY_address(0,3);
02413         //      Lcd_SelectionBar((CountedFiles-file_number), CountedFiles);
02414         print_D64_name(INVERTED);                        /*write the selection to display in inverted mode*/
02415         DelayBigMs(BUTTON_SELECTION_RATE);                /*delay determines selection repetition rate*/
02416     }
02417 
02418     if    (button_select == TRUE) {
02419         filefilter_result = FileFilter();                /*check the selected file*/
02420         file_type = filefilter_result;
02421 
02422         if (file_number==0) {                              /*file counter is now '0' which means 'ROOT directory'*/
02423             file_type = NONE;                            /*and because the user has selected root, the selected file_type = NONE*/
02424             //        Lcd_XY_address(0,2);                        /*set cursor*/
02425             printf("              ");                    /*clear the file_info information*/
02426             print_D64_name(PLAIN);                        /*write the selection to display in normal-mode*/
02427             DiskState = CARD_ACTIVE;                    /*the 1541-III is now functioning as a harddisk*/
02428             DelayBigMs(BUTTON_SELECTION_RATE);            /*delay determines selection repetition rate*/
02429         } else {
02430             if (filefilter_result == SUBDIRECTORY) {
02431                 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*/
02432                 file_number = 0;                            /*the file_number counter needs to be reset*/
02433                 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*/
02434 
02435                 print_D64_name(PLAIN);                        /*write the selection to display in normal-mode, this clears up the display, but with the incorrect filecount values*/
02436                 CountFiles();                                /*count all files in the opened directory*/
02437                 print_D64_name(PLAIN);                        /*write the selection to display in normal-mode, the countvalues are updated*/
02438                 //          Lcd_XY_address(0,2);                        /*set cursor*/
02439                 printf("              ");                    /*clear the file_info information*/
02440                 DiskState = CARD_ACTIVE;                    /*the 1541-III is now functioning as a harddisk*/
02441                 DelayBigMs(BUTTON_SELECTION_RATE);            /*delay determines selection repetition rate*/
02442             } else {
02443                 if ((filefilter_result != PRG_FILE) && (filefilter_result != UNKNOWN)) {  /*pass all supported D64 files and leave out PRG and unknown files*/
02444                     FileSectorScan(&file);                    /*update the sector location table cache*/
02445                     D64ReadBAM();                            /*update the BAM*/
02446                     DiskState = CARD_ACTIVE;                /*the 1541-III is now accessable*/
02447                     //            Lcd_XY_address(0,2);                    /*set cursor*/
02448                     printf("              ");                /*clear the file_info information*/
02449                     print_D64_name(PLAIN);                    /*write the selection to display in normal-mode*/
02450                 } else {
02451                     for (blink_loop=4; blink_loop>0; blink_loop--) { /*create a blinking effect to draw attention to this line*/
02452                         //              Lcd_CharInvert();
02453                         //            Lcd_XY_address(0,1);
02454                         printf("Selection err.");
02455                         DelayBigMs(250);                    /*delay to make sure the message can be read properly*/
02456                         //          Lcd_CharNormal();
02457                         //        Lcd_XY_address(0,1);
02458                         printf("Selection err.");
02459                         DelayBigMs(250);                    /*delay to make sure the message can be read properly*/
02460                     }
02461                     print_D64_name(INVERTED);                /*write the selection to display in inverted mode*/
02462                 }
02463             }
02464         }
02465     }
02466 }
02467 
02468 /*****************************************************************************************************************/
02469 /*almost identical to loading a directory (seen from a C64)*/
02470 /*This routine shows 'all' the files on the card*/
02471 
02472 /*Note: 'all' means the files that are OK according the filefilter routine*/
02473 void CardDirectory(void) {
02474     unsigned pass_counter;
02475     unsigned char separation_line=FALSE;
02476     unsigned char filefilter_result;
02477     unsigned int index_cnt;
02478     unsigned char lp;
02479     unsigned char dir_width;
02480     unsigned int blocksize;
02481 
02482     SetErrorCode(0,LED_ON);        /*unless we fail we will exit with no error*/
02483     EOI = FALSE;
02484     IEC_turnaround();            /*we now SEND data to the bus so... make our device a talker*/
02485 
02486     /*----------------*/
02487     /*directory header*/
02488     /*----------------*/
02489     IEC_send(0x01);                /*load this "program" to start address 0x0401*/
02490     IEC_send(0x04);
02491 
02492     if (VIC20_mode == TRUE)        /*for better readabillity on a VIC-20 the card directory is displayed in a smallscreen and a widescreen version*/
02493     {                            /*                                                                                                       |              |*/ /*useable area of a VC-20 dir line*/
02494         dir_width = 10;            /*the number of places that a VIC20 file entry may occupy in order to fit the screen width of 22 chars*/
02495         IEC_send(0x01);
02496         IEC_send(0x01);
02497         IEC_send(0x00);
02498         IEC_send(0x00);
02499         IEC_send(0x20);
02500         IEC_send(0x12);
02501         IEC_send(0x20);
02502         IEC_send(0x22);
02503         IEC_send_string("CARD DIRECTORY");
02504         IEC_send(0x22);
02505         IEC_send(0x00);    /*VIC-20 Directory header*/
02506         IEC_send(0x01);
02507         IEC_send(0x01);
02508         IEC_send(0x00);
02509         IEC_send(0x00);
02510         IEC_send(0x20);
02511         IEC_send(0x20);
02512         IEC_send(0x22);
02513         IEC_send_string("u``````````i");
02514         IEC_send(0x22);
02515         IEC_send(0x00);    /*top-line*/
02516         IEC_send(0x01);
02517         IEC_send(0x01);
02518         IEC_send(0x00);
02519         IEC_send(0x00);
02520         IEC_send(0x20);
02521         IEC_send(0x20);
02522         IEC_send(0x22);
02523         IEC_send_string("} 1541-III }");
02524         IEC_send(0x22);
02525         IEC_send(0x00);    /*model*/
02526         IEC_send(0x01);
02527         IEC_send(0x01);
02528         IEC_send(0x00);
02529         IEC_send(0x00);
02530         IEC_send(0x20);
02531         IEC_send(0x20);
02532         IEC_send(0x22);
02533         IEC_send_string("}J. DEROGEE}");
02534         IEC_send(0x22);
02535         IEC_send(0x00);    /*credits*/
02536         IEC_send(0x01);
02537         IEC_send(0x01);
02538         IEC_send(0x00);
02539         IEC_send(0x00);
02540         IEC_send(0x20);
02541         IEC_send(0x20);
02542         IEC_send(0x22);
02543         IEC_send_string("}VIC20-MODE}");
02544         IEC_send(0x22);
02545         IEC_send(0x00);    /*credits*/
02546         IEC_send(0x01);
02547         IEC_send(0x01);
02548         IEC_send(0x00);
02549         IEC_send(0x00);
02550         IEC_send(0x20);
02551         IEC_send(0x20);
02552         IEC_send(0x22);
02553         IEC_send_string("j``````````k");
02554         IEC_send(0x22);
02555         IEC_send(0x00);    /*separation-line*/
02556     } else {
02557         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*/
02558         IEC_send(0x01);
02559         IEC_send(0x01);
02560         IEC_send(0x00);
02561         IEC_send(0x00);
02562         IEC_send(0x20);
02563         IEC_send(0x12);
02564         IEC_send(0x20);
02565         IEC_send(0x22);
02566         IEC_send_string(" CARD DIRECTORY ");
02567         IEC_send(0x22);
02568         IEC_send_string(" 00 2A");
02569         IEC_send(0x00);    /*Normal Directory header*/
02570         IEC_send(0x01);
02571         IEC_send(0x01);
02572         IEC_send(0x00);
02573         IEC_send(0x00);
02574         IEC_send(0x20);
02575         IEC_send(0x20);
02576         IEC_send(0x22);
02577         IEC_send_string("u````````````````i");
02578         IEC_send(0x22);
02579         IEC_send(0x00);    /*top-line*/
02580         IEC_send(0x01);
02581         IEC_send(0x01);
02582         IEC_send(0x00);
02583         IEC_send(0x00);
02584         IEC_send(0x20);
02585         IEC_send(0x20);
02586         IEC_send(0x22);
02587         IEC_send_string("} 1541-III MBED  }");
02588         IEC_send(0x22);
02589         IEC_send(0x00);    /*model*/
02590         IEC_send(0x01);
02591         IEC_send(0x01);
02592         IEC_send(0x00);
02593         IEC_send(0x00);
02594         IEC_send(0x20);
02595         IEC_send(0x20);
02596         IEC_send(0x22);
02597         IEC_send_string("}J.DEROGEE & KGE }");
02598         IEC_send(0x22);
02599         IEC_send(0x00);    /*credits*/
02600         IEC_send(0x01);
02601         IEC_send(0x01);
02602         IEC_send(0x00);
02603         IEC_send(0x00);
02604         IEC_send(0x20);
02605         IEC_send(0x20);
02606         IEC_send(0x22);
02607         IEC_send_string("j````````````````k");
02608         IEC_send(0x22);
02609         IEC_send(0x00);    /*separation-line*/
02610     }
02611 
02612     /*-----------------*/
02613     /*directory content*/
02614     /*-----------------*/
02615 
02616     pass_counter = 0;
02617     index_cnt = 0;
02618     while (pass_counter++ < 3) {
02619         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)*/
02620             separation_line = FALSE;
02621 
02622         if (FileSearch(&file,0)) {
02623             do {
02624                 //OutputToRS232();                                                        /*set standard output to RS232*/
02625                 //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 !!!*/
02626                 //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 !!!*/
02627                 //OutputToLCD();                                                            /*set standard output to LCD*/
02628 
02629                 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)*/
02630                 index_cnt++;    /*for the best results... arrange the files on filetype, directories first, the D64's of all types, then PRG-files*/
02631                 filefilter_result = FileFilter();
02632                 if ((pass_counter == 1) && (filefilter_result == SUBDIRECTORY) ||
02633                         ((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))) ||
02634                         ((pass_counter == 3) && ((filefilter_result == PRG_FILE) || (filefilter_result == T64_MODE) || (filefilter_result == UNKNOWN)))) {
02635                     if (separation_line == FALSE) {      /*for better readabillity... add a small separation-line (but only if required)*/
02636                         separation_line = TRUE;
02637                         IEC_send(0x01);
02638                         IEC_send(0x01);
02639                         IEC_send(0x00);
02640                         IEC_send(0x00);
02641                         IEC_send(0x20);
02642                         IEC_send(0x20);
02643                         IEC_send(0x22);
02644                         for (lp=0; lp<(dir_width+1); lp++)
02645                             IEC_send('`');
02646                         IEC_send(0x22);
02647                         IEC_send(0x00);
02648                     }
02649 
02650                     IEC_send(0x01);
02651                     IEC_send(0x01);
02652 
02653                     if (pass_counter == 3) {              /*in the third pass we show all the file information, as these are not images or directories, but actual files*/
02654                         blocksize = file.size / 254;    /*calculate blocksize(1 block=254 bytes) from filesize(bytes)*/
02655                         IEC_send(blocksize%256);        /*low-byte of blocksize of file*/
02656                         IEC_send(blocksize/256);        /*high-byte of  blocksize of file*/
02657                         if (blocksize < 10)               /*if required, add extra space for better allignment*/
02658                             IEC_send(0x20);
02659 
02660                         if (blocksize < 100)               /*if required, add extra space for better allignment*/
02661                             IEC_send(0x20);
02662                     } else {
02663                         IEC_send(0);                    /*low-byte of blocksize of file*/
02664                         IEC_send(0);                    /*high-byte of blocksize of file*/
02665                         IEC_send(0x20);
02666                         IEC_send(0x20);
02667                     }
02668 
02669                     IEC_send(0x22);                 /*each entry must be starting with the "-sign*/
02670                     if ((filefilter_result != PRG_FILE) && (filefilter_result != UNKNOWN))
02671                         IEC_send('$');                /*proceed each image (.D64 or similar) or subdirectory with a $-sign, to indicate that it has to be loaded as an directory*/
02672 
02673                     if (file.name_lfn[0] == 0) {     /*check if this entry has an 8.3-name or LFN-name*/
02674                         IEC_send(file.name[0]);        /*8.3 filename WITHOUT the extra spaces (looks much better as the LFN has the same look by nature)*/
02675                         lp=7;
02676                         if (((file.name[1]) != ' ') || ((file.name[2]) != ' ') || ((file.name[3]) != ' ') || ((file.name[4]) != ' ') || ((file.name[5]) != ' ') || ((file.name[6]) != ' ') || ((file.name[7]) != ' ')) {
02677                             IEC_send(file.name[1]);
02678                             lp=6;
02679                         }
02680                         if (((file.name[2]) != ' ') || ((file.name[3]) != ' ') || ((file.name[4]) != ' ') || ((file.name[5]) != ' ') || ((file.name[6]) != ' ') || ((file.name[7]) != ' ')) {
02681                             IEC_send(file.name[2]);
02682                             lp=5;
02683                         }
02684                         if (((file.name[3]) != ' ') || ((file.name[4]) != ' ') || ((file.name[5]) != ' ') || ((file.name[6]) != ' ') || ((file.name[7]) != ' ')) {
02685                             IEC_send(file.name[3]);
02686                             lp=4;
02687                         }
02688                         if (((file.name[4]) != ' ') || ((file.name[5]) != ' ') || ((file.name[6]) != ' ') || ((file.name[7]) != ' ')) {
02689                             IEC_send(file.name[4]);
02690                             lp=3;
02691                         }
02692                         if (((file.name[5]) != ' ') || ((file.name[6]) != ' ') || ((file.name[7]) != ' ')) {
02693                             IEC_send(file.name[5]);
02694                             lp=2;
02695                         }
02696                         if (((file.name[6]) != ' ') || ((file.name[7]) != ' ')) {
02697                             IEC_send(file.name[6]);
02698                             lp=1;
02699                         }
02700                         if ((file.name[7]) != ' ') {
02701                             IEC_send(file.name[7]);
02702                             lp=0;
02703                         }
02704 
02705                         lp = (dir_width - 7) + lp;                    /*calculate the remaining spaces to fit the VIC20 mode*/
02706                     } else {
02707                         for (lp=0; lp<(dir_width-1); lp++) {           /*print the LFN string*/
02708                             IEC_send(file.name_lfn[lp]);
02709                             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)*/
02710                                 break;
02711 
02712                             if (file.name_lfn[lp+1] == 0)            /*otherwise on end of string, stop*/
02713                                 break;
02714                         }
02715 
02716                         if (lp==(dir_width-1))                        /*check if the filename was displayed partially, if so, then add a *-sign*/
02717                             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*/
02718 
02719                         lp = dir_width  - lp;                        /*calculate the remaining number of spaces*/
02720                     }
02721 
02722                     IEC_send(0x22);                                    /*each entry must end with the "-sign*/
02723                     if (filefilter_result == PRG_FILE)
02724                         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*/
02725 
02726                     while (lp--)                                       /*the remaining location must be filled with spaces*/
02727                         IEC_send(' ');
02728 
02729                     switch (filefilter_result) {
02730                         case PRG_FILE: {
02731                             IEC_send('P');                            /*print PRG*/
02732                             IEC_send('R');
02733                             IEC_send('G');
02734                             break;
02735                         }
02736 
02737                         case D64_35T_MODE:
02738                             ;
02739                         case D64_35T_ER_MODE:
02740                             ;
02741                         case D64_40T_MODE:
02742                             ;
02743                         case D64_40T_ER_MODE: {
02744                             IEC_send('D');                            /*print D64*/
02745                             IEC_send('6');
02746                             IEC_send('4');
02747                             break;
02748                         }
02749 
02750                         case T64_MODE: {
02751                             IEC_send('T');                            /*print T64*/
02752                             IEC_send('6');
02753                             IEC_send('4');
02754                             break;
02755                         }
02756 
02757                         case SUBDIRECTORY: {
02758                             IEC_send('D');                            /*print DIR*/
02759                             IEC_send('I');
02760                             IEC_send('R');
02761                             break;
02762                         }
02763 
02764                         default: {
02765                             break;                                    /*print nothing*/
02766                         }
02767                     }
02768 
02769                     IEC_send(0x00);
02770                 }
02771             } while (FileSearch(&file,1));
02772         }
02773     }
02774 
02775     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*/
02776 
02777     /*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*/
02778     IEC_send(0x00);
02779     EOI = TRUE;                                /*indicate the last byte*/
02780     IEC_send(0x00);
02781     IEC_undoturnaround();                    /*were done talking towards the bus*/
02782     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*/
02783 }
02784 
02785 
02786 void D64Directory(void) {
02787     unsigned char lp, mode, extra_spaces, track, sector, unused;
02788     unsigned int blocksize, blocksfree, read_blocks;
02789 
02790     SetErrorCode(0,LED_ON);         /*unless we fail we will exit with no error*/
02791     EOI = FALSE;
02792     IEC_turnaround();                /*we now SEND data to the bus so... make our device a talker*/
02793 
02794     /*some bytes required for sending a directory entry to a VIC20, C64, C128, etc.*/
02795     IEC_send(0x01);                    /*load this "program" to start address 0x0401*/
02796     IEC_send(0x04);
02797 
02798     /*Directory header*/
02799     /*----------------*/
02800     D64BlockRead(18,0);
02801     read_blocks = 1;
02802     print_D64_TSB(18,0,read_blocks, 0);
02803     IEC_send(0x01);                    /*...*/
02804     IEC_send(0x01);                    /*...*/
02805     IEC_send(0);        /*drive-number of this device, in the beginning of this project used as file pointer/indicator*/
02806     IEC_send(0);        /*drive-number of this device, in the beginning of this project uses as file pointer/indicator*/
02807     IEC_send(0x12);                    /*RVS-ON (invert characters)*/
02808     IEC_send(0x22);                    /*"-sign*/
02809     for (lp=144; lp<160; lp++) {
02810         IEC_send(RAM_buffer[lp]);    /*send the Diskname*/
02811     }
02812 
02813     IEC_send(0x22);                    /*"-sign*/
02814     IEC_send(0x20);                    /*space*/
02815     IEC_send(RAM_buffer[162]);        /*send the disk-ID byte-0*/
02816     IEC_send(RAM_buffer[163]);        /*send the disk-ID byte-1*/
02817     IEC_send(0x20);                    /*space*/
02818     IEC_send(RAM_buffer[165]);        /*send the DOS-version and format-type byte-0*/
02819     IEC_send(RAM_buffer[166]);        /*send the DOS-version and format-type byte-1*/
02820     IEC_send(0x00);                    /*a byte indicating the end of this "directory-line"*/
02821 
02822     /*Directory entry ...*/
02823     /*-------------------*/
02824     mode=0;    /*set sector read to first entry*/
02825     while (D64SeekDirEntry(mode, &track, &sector, &unused)) {     /*get directory entry and request the current track and sector*/
02826         mode=1;    /*set sector read to next entry*/
02827         print_D64_TSB(track,sector,read_blocks,0);
02828         if (dir_entry.filetype != 0x00) {               /*scratched files are NOT displayed in the directory*/
02829             IEC_send(0x01);                                /*bytes indicating the beginning of a "directory-line"*/
02830             IEC_send(0x01);
02831             IEC_send(dir_entry.blocksize_low_byte);        /*size of this file low-byte*/
02832             IEC_send(dir_entry.blocksize_high_byte);    /*size of this file high-byte*/
02833 //    dir_entry.record_size_relfile = 0x00;
02834             blocksize = ((256 * dir_entry.blocksize_high_byte) + dir_entry.blocksize_low_byte);
02835             if (blocksize < 10)                            /*add an extra space(s) to adjust line length*/
02836                 IEC_send(0x20);                            /*                                           */
02837             if (blocksize < 100)                        /*                                           */
02838                 IEC_send(0x20);                            /*                                           */
02839             if (blocksize < 1000)                        /*                                           */
02840                 IEC_send(0x20);                            /*                                           */
02841             IEC_send(0x22);                                /*"-sign*/
02842 
02843             extra_spaces = 0;
02844             for (lp=0; lp<16; lp++) {
02845                 if (dir_entry.filename[lp]== 160)
02846                     extra_spaces++;
02847                 else
02848                     IEC_send(dir_entry.filename[lp]);        /*filename of this entrynumber*/
02849 
02850             }
02851 
02852             IEC_send(0x22);                            /*"-sign*/
02853             while (extra_spaces != 0) {
02854                 IEC_send(0x20);                        /*add some extra spaces for proper allignment*/
02855                 extra_spaces--;
02856             }
02857 
02858             /*filetype*/
02859             /*--------*/
02860             if (dir_entry.filetype > 127)            /*when MSB has been set the file has been properly closed*/
02861                 IEC_send(0x20);                        /*print a space before the filetype*/
02862             else
02863                 IEC_send(0x2A);                        /*print a asterix before the filetype to indicate that the file has not been closed (yet)*/
02864 
02865             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 ...*/
02866                 case 0: {
02867                     IEC_send(0x44);                    /*file type = DELeted */
02868                     IEC_send(0x45);
02869                     IEC_send(0x4C);
02870                     break;
02871                 }
02872 
02873                 case 1: {
02874                     IEC_send(0x53);                    /*file type = SEQuential */
02875                     IEC_send(0x45);
02876                     IEC_send(0x51);
02877                     break;
02878                 }
02879 
02880                 case 2: {
02881                     IEC_send(0x50);                    /*file type = PRoGram */
02882                     IEC_send(0x52);
02883                     IEC_send(0x47);
02884                     break;
02885                 }
02886 
02887                 case 3: {
02888                     IEC_send(0x55);                    /*file type = USeR */
02889                     IEC_send(0x53);
02890                     IEC_send(0x52);
02891                     break;
02892                 }
02893 
02894 
02895                 case 4: {
02896                     IEC_send(0x52);                    /*file type = RELative */
02897                     IEC_send(0x45);
02898                     IEC_send(0x4C);
02899                     break;
02900                 }
02901 
02902                 default: {
02903                     IEC_send(0x55);                    /*file type = UNKnown (is only shown if someone uses these values out of spec...*/
02904                     IEC_send(0x4E);
02905                     IEC_send(0x4B);
02906                     break;
02907                 }
02908             }
02909 
02910             if (dir_entry.filetype > 191)
02911                 IEC_send(0x3C);                        /*print a "<" to indicate a locked file*/
02912             else
02913                 IEC_send(0x20);
02914 
02915             IEC_send(0x20);
02916             IEC_send(0x20);
02917             IEC_send(0x20);
02918             IEC_send(0x00);
02919         }
02920     }
02921 
02922     /*Blocks free "directory-line"*/
02923     /*----------------------------*/
02924     IEC_send(0x01);
02925     IEC_send(0x01);
02926     blocksfree = D64LoadFreeBlocks();        /*read the number of free blocks from the D64 file*/
02927     IEC_send(blocksfree%256);                /*low-byte of free blocks value*/
02928     IEC_send(blocksfree/256);                /*high-byte of free blocks value*/
02929     IEC_send_string("BLOCKS FREE.               ");    /*"Blocks free."*/
02930     IEC_send(0x00);
02931     IEC_send(0x00);
02932     EOI = TRUE;                                /*indicate the last byte*/
02933     IEC_send(0x00);
02934     IEC_undoturnaround();                    /*were done talking towards the bus*/
02935     SetErrorCode(0, LED_OFF);                /*all is OK*/
02936 }
02937 
02938 void T64Directory(void) {
02939     unsigned char lp, mode, extra_spaces, track, sector, unused;
02940     unsigned int blocksize, blocksfree, read_blocks;
02941 
02942     SetErrorCode(0,LED_ON);         /*unless we fail we will exit with no error*/
02943     EOI = FALSE;
02944     IEC_turnaround();                /*we now SEND data to the bus so... make our device a talker*/
02945 
02946     /*some bytes required for sending a directory entry to a VIC20, C64, C128, etc.*/
02947     IEC_send(0x01);                    /*load this "program" to start address 0x0401*/
02948     IEC_send(0x04);
02949 
02950     /*Directory header*/
02951     /*----------------*/
02952     D64BlockRead(18,0);
02953     read_blocks = 1;
02954     print_D64_TSB(18,0,read_blocks, 0);
02955     IEC_send(0x01);                    /*...*/
02956     IEC_send(0x01);                    /*...*/
02957     IEC_send(0);        /*drive-number of this device, in the beginning of this project used as file pointer/indicator*/
02958     IEC_send(0);        /*drive-number of this device, in the beginning of this project uses as file pointer/indicator*/
02959     IEC_send(0x12);                    /*RVS-ON (invert characters)*/
02960     IEC_send(0x22);                    /*"-sign*/
02961     for (lp=144; lp<160; lp++) {
02962         IEC_send(RAM_buffer[lp]);    /*send the Diskname*/
02963     }
02964 
02965     IEC_send(0x22);                    /*"-sign*/
02966     IEC_send(0x20);                    /*space*/
02967     IEC_send(RAM_buffer[162]);        /*send the disk-ID byte-0*/
02968     IEC_send(RAM_buffer[163]);        /*send the disk-ID byte-1*/
02969     IEC_send(0x20);                    /*space*/
02970     IEC_send(RAM_buffer[165]);        /*send the DOS-version and format-type byte-0*/
02971     IEC_send(RAM_buffer[166]);        /*send the DOS-version and format-type byte-1*/
02972     IEC_send(0x00);                    /*a byte indicating the end of this "directory-line"*/
02973 
02974     /*Directory entry ...*/
02975     /*-------------------*/
02976     mode=0;    /*set sector read to first entry*/
02977     while (D64SeekDirEntry(mode, &track, &sector, &unused)) {     /*get directory entry and request the current track and sector*/
02978         mode=1;    /*set sector read to next entry*/
02979         print_D64_TSB(track,sector,read_blocks,0);
02980         if (dir_entry.filetype != 0x00) {               /*scratched files are NOT displayed in the directory*/
02981             IEC_send(0x01);                                /*bytes indicating the beginning of a "directory-line"*/
02982             IEC_send(0x01);
02983             IEC_send(dir_entry.blocksize_low_byte);        /*size of this file low-byte*/
02984             IEC_send(dir_entry.blocksize_high_byte);    /*size of this file high-byte*/
02985 //    dir_entry.record_size_relfile = 0x00;
02986             blocksize = ((256 * dir_entry.blocksize_high_byte) + dir_entry.blocksize_low_byte);
02987             if (blocksize < 10)                            /*add an extra space(s) to adjust line length*/
02988                 IEC_send(0x20);                            /*                                           */
02989             if (blocksize < 100)                        /*                                           */
02990                 IEC_send(0x20);                            /*                                           */
02991             if (blocksize < 1000)                        /*                                           */
02992                 IEC_send(0x20);                            /*                                           */
02993             IEC_send(0x22);                                /*"-sign*/
02994 
02995             extra_spaces = 0;
02996             for (lp=0; lp<16; lp++) {
02997                 if (dir_entry.filename[lp]== 160)
02998                     extra_spaces++;
02999                 else
03000                     IEC_send(dir_entry.filename[lp]);        /*filename of this entrynumber*/
03001 
03002             }
03003 
03004             IEC_send(0x22);                            /*"-sign*/
03005             while (extra_spaces != 0) {
03006                 IEC_send(0x20);                        /*add some extra spaces for proper allignment*/
03007                 extra_spaces--;
03008             }
03009 
03010             /*filetype*/
03011             /*--------*/
03012             if (dir_entry.filetype > 127)            /*when MSB has been set the file has been properly closed*/
03013                 IEC_send(0x20);                        /*print a space before the filetype*/
03014             else
03015                 IEC_send(0x2A);                        /*print a asterix before the filetype to indicate that the file has not been closed (yet)*/
03016 
03017             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 ...*/
03018                 case 0: {
03019                     IEC_send(0x44);                    /*file type = DELeted */
03020                     IEC_send(0x45);
03021                     IEC_send(0x4C);
03022                     break;
03023                 }
03024 
03025                 case 1: {
03026                     IEC_send(0x53);                    /*file type = SEQuential */
03027                     IEC_send(0x45);
03028                     IEC_send(0x51);
03029                     break;
03030                 }
03031 
03032                 case 2: {
03033                     IEC_send(0x50);                    /*file type = PRoGram */
03034                     IEC_send(0x52);
03035                     IEC_send(0x47);
03036                     break;
03037                 }
03038 
03039                 case 3: {
03040                     IEC_send(0x55);                    /*file type = USeR */
03041                     IEC_send(0x53);
03042                     IEC_send(0x52);
03043                     break;
03044                 }
03045 
03046 
03047                 case 4: {
03048                     IEC_send(0x52);                    /*file type = RELative */
03049                     IEC_send(0x45);
03050                     IEC_send(0x4C);
03051                     break;
03052                 }
03053 
03054                 default: {
03055                     IEC_send(0x55);                    /*file type = UNKnown (is only shown if someone uses these values out of spec...*/
03056                     IEC_send(0x4E);
03057                     IEC_send(0x4B);
03058                     break;
03059                 }
03060             }
03061 
03062             if (dir_entry.filetype > 191)
03063                 IEC_send(0x3C);                        /*print a "<" to indicate a locked file*/
03064             else
03065                 IEC_send(0x20);
03066 
03067             IEC_send(0x20);
03068             IEC_send(0x20);
03069             IEC_send(0x20);
03070             IEC_send(0x00);
03071         }
03072     }
03073 
03074     /*Blocks free "directory-line"*/
03075     /*----------------------------*/
03076     IEC_send(0x01);
03077     IEC_send(0x01);
03078     blocksfree = D64LoadFreeBlocks();        /*read the number of free blocks from the D64 file*/
03079     IEC_send(blocksfree%256);                /*low-byte of free blocks value*/
03080     IEC_send(blocksfree/256);                /*high-byte of free blocks value*/
03081     IEC_send_string("BLOCKS FREE.               ");    /*"Blocks free."*/
03082     IEC_send(0x00);
03083     IEC_send(0x00);
03084     EOI = TRUE;                                /*indicate the last byte*/
03085     IEC_send(0x00);
03086     IEC_undoturnaround();                    /*were done talking towards the bus*/
03087     SetErrorCode(0, LED_OFF);                /*all is OK*/
03088 }
03089 
03090 
03091 /*this routine will search for a file ON THE CARD that matches the given filename search pattern*/
03092 /*the return value (if file is found) will be the index-number of the file as stored on the card*/
03093 unsigned int SeekFileOnCard(unsigned char *filename, struct file2TYPE *file) {
03094     signed char lp;
03095     unsigned int index;
03096 
03097     index = 0;                    /*reset the index counter, as we do whish to know what the index of this file (within this (sub)directory) is*/
03098     if (!FileSearch(file, 0))    /*search for the first file on the card. Attention: screws up secbuf!!*/
03099         return(FALSE);
03100     while (1) {
03101         index++;
03102         lp = -1;        /*reset loopcounter*/
03103         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*/
03104             if (file->name_lfn[0] == 0)                   /*check if this entry has an 8.3-name or LFN-name*/
03105             {        /*this file has no LFN name so we must use the 8.3 information for further searching*/
03106                 do {  /*----------------------------------------------------------------------------------*/
03107                     lp++;
03108                     //    OutputToRS232();                                                    /*set standard output to RS232*/
03109                     //    printf("\r\n8.3:lp=%02X, %c, %c",lp, file->name[lp], filename[lp]);    /*for debug purposes only !!!*/
03110                     //    OutputToLCD();                                                        /*set standard output to LCD*/
03111 
03112                     if ((filename[lp] == 0) && (lp==8))   /*when we've succesfully matched all 8 chars of the 8.3 name... we have a match*/
03113                         return(index);                    /*all the remaining characters of the current file are spaces, we have a match!!!*/
03114 
03115                     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*/
03116                         while (lp<8) {
03117                             if (file->name[lp] != ' ')
03118                                 break;
03119                             if (lp==7)
03120                                 return(index);                /*all the remaining characters of the current file are spaces, we have a match!!!*/
03121                             lp++;
03122                         }
03123 
03124                     if (filename[lp] == 0)                /*when the search string has not been ended but the searched filename has... no match*/
03125                         break;                            /*we have no match*/
03126 
03127                     /*wildcard filter*/
03128                     if (filename[lp] == '?')            /*when we encounter an '?', it does not matter what the real char of the filename is*/
03129                         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*/
03130 
03131                     if (filename[lp] == '*')            /*when we have come so far and detected a * in our search string... we may consider this a match*/
03132                         return(index);                        /*we have a partial or possible 100% match... but good enough to return with TRUE*/
03133                 } while (file->name[lp] == filename[lp]);  /*do the compare of current char of both strings*/
03134             } else   /*this file has an LFN entry, use this for searching*/
03135             {        /*--------------------------------------------------*/
03136                 do {
03137                     lp++;
03138                     //    OutputToRS232();                                                        /*set standard output to RS232*/
03139                     //    printf("\r\nLFN:lp=%02X, %c, %c",lp, file->name_lfn[lp], filename[lp]);    /*for debug purposes only !!!*/
03140                     //    OutputToLCD();                                                            /*set standard output to LCD*/
03141 
03142                     if ((filename[lp] == 0) && (file->name_lfn[lp]== '.'))   /*when we have reached the extension if the file, we may consider this a match*/
03143                         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 ?!?!*/
03144 
03145                     if ((filename[lp] == 0) && (file->name_lfn[lp]== 0))   /*when we have reached the end of both strings, this is the perfect match*/
03146                         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 ?!?!*/
03147 
03148                     if (filename[lp] == 0)                    /*when the search string has not been ended but the searched filename has... no match*/
03149                         break;                                /*we have no match*/
03150 
03151                     /*wildcard filter*/
03152                     if (filename[lp] == '?')                /*when we encounter an '?', it does not matter what the real char of the filename is*/
03153                         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*/
03154 
03155                     if (filename[lp] == '*')                /*when we have come so far and detected a * in our search string... we may consider this a match*/
03156                         return(index);                            /*we have a partial or possible 100% match... but good enough to return with TRUE*/
03157                 } while (file->name_lfn[lp] == filename[lp]);  /*do the compare of current char of both strings*/
03158             }
03159         }
03160         if (!FileSearch(file, 1))                    /*search for the next file on the card. Attention: screws up secbuf!!*/
03161             break;
03162     }
03163     return(FALSE);
03164 }
03165 
03166 /*this routine will load the file indicated by the given struct*/
03167 void LoadFileFromCard(struct file2TYPE *file) {
03168     unsigned char    bytecount;
03169     unsigned int    lp, blocksrem, filesizeinblocks;
03170     unsigned long    remainingbytecounter;
03171 
03172     SetErrorCode(0,LED_ON);                    /*unless we fail we will exit with no error*/
03173     EOI = FALSE;
03174     IEC_turnaround();                        /*we now SEND data to the bus so... make our device a talker*/
03175     remainingbytecounter = file->size;
03176     lp = 0;
03177     bytecount = 0;
03178 
03179     /*calculate the blocksize of this file*/
03180     blocksrem = remainingbytecounter / 254;
03181     filesizeinblocks = blocksrem;
03182     if ((remainingbytecounter % 254) > 0)
03183         blocksrem++;
03184     blocksrem--;                    /*decrement by one, otherwise the countdown will stop at 1, and it must (offcourse) stop at 0*/
03185 
03186     FileReadSector(file);            /*read the first sector from the card (this is NOT a D64 sector) and contains MORE then 256 bytes*/
03187     while (remainingbytecounter != 0) {
03188         if (bytecount == 0)
03189             SetErrorCode(0,LED_ON);            /*turn LED on, to create a small blink at every block*/
03190         if (bytecount == Blink_block)
03191             SetErrorCode(0,LED_OFF);        /*turn LED off, to create a small blink at every block*/
03192 
03193         if (remainingbytecounter == 1) {      /*check for last byte*/
03194             EOI = TRUE;                        /*indicate the last byte*/
03195         }
03196 
03197         IEC_send(block_buffer[lp]);
03198         remainingbytecounter--;
03199         bytecount++;
03200         lp++;
03201 
03202         if (lp == 512) {
03203             FileNextSector(file);        /*we must set file pointer to the next sector before we can read the next sector*/
03204             FileReadSector(file);        /*its time to read another sector*/
03205             lp = 0;
03206         }
03207 
03208         if (bytecount == 254) {
03209             blocksrem--;                                        /*another block has been send... update counter*/
03210             print_D64_TSB(0, 0, blocksrem, filesizeinblocks);    /*print track, sector and remaining blocks*/
03211             bytecount = 0;
03212         }
03213     }
03214 
03215     IEC_undoturnaround();            /*were done talking towards the bus*/
03216     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*/
03217 }
03218 
03219 void LoadD64File(unsigned char trk, unsigned char sec, unsigned int filesizeinblocks) {
03220     unsigned char lp;
03221     unsigned int blocksrem;
03222     unsigned char lasttrack, lastsector;
03223 
03224     blocksrem = filesizeinblocks;
03225     EOI = FALSE;
03226     IEC_turnaround();                        /*we now SEND data to the bus so... make our device a talker*/
03227 
03228     while (1) {
03229         SetErrorCode(0,LED_ON);                                    /*unless we fail we will exit with no error*/
03230         print_D64_TSB(trk, sec, blocksrem, filesizeinblocks);    /*print track, sector and remaining blocks*/
03231         lasttrack = trk;                                        /*keep extra buffer to remember what the last track was*/
03232         lastsector = sec;                                        /*keep extra buffer to remember what the last sector was*/
03233         D64LoadFile_X_Bytes(&file,trk,sec,0,256);                /*location of block to load and its size in bytes*/
03234         trk = block_buffer[0];                                    /*track position of the next block*/
03235         sec = block_buffer[1];                                    /*sector position of the next block*/
03236         blocksrem--;                                            /*decrement remaining blocks counter*/
03237 
03238         if (trk != 0) {                                          /*check on last block*/
03239             for (lp=2; lp!=0; lp++) {
03240                 IEC_send(block_buffer[lp]);                    /*transmit the 254 bytes within this block to the listener*/
03241                 if (lp == Blink_block)
03242                     SetErrorCode(0,LED_OFF);                /*turn LED off, to create a small blink at every block*/
03243             }
03244         } else {                                                 /*transmission of data of the last block*/
03245             print_D64_TSB(lasttrack, lastsector, blocksrem, filesizeinblocks);        /*print track, sector of the last block*/
03246             for (lp=2; lp<(sec); lp++)                         /*transfer the remainder of the loaded last block*/
03247                 IEC_send(block_buffer[lp]);
03248             break;
03249         }
03250     }
03251     EOI = TRUE;                                /*indicate the last byte*/
03252     IEC_send(block_buffer[sec]);                /*the position of the last byte is indicated by the value in register 'Sector'*/
03253     IEC_undoturnaround();                    /*were done talking towards the bus*/
03254     SetErrorCode(0,LED_OFF);                /*all is OK*/
03255 }
03256 
03257 /*Save the file to the D64, this requires the complete DOS handling !!!, since the CBM does not send*/
03258 /*the filesize, the exact filesize is only known when the file has allready been written. This is too*/
03259 /*late to update the progressbar on the LCD, so that's why this bar does not behave as expected*/
03260 unsigned char SaveD64File(void) {
03261     unsigned char lp, fbpt, firsttrack, firstsector, bytecounter;
03262     unsigned char track, sector, nexttrack, nextsector;
03263     unsigned int blocksize;
03264 
03265     blocksize = 0;
03266 
03267     /*search for the first block location of the file to be saved*/
03268     if (!D64SeekFreeBlock(&track, &sector)) {
03269         SetErrorCode(72,LED_ERROR);                            /*error: disk or directory full*/
03270         return(FALSE);
03271     }
03272 
03273     firsttrack = track;
03274     firstsector = sector;
03275     nexttrack = track;                                        /*update the track variable*/
03276     nextsector = sector;                                    /*update the track variable*/
03277     EOI = 0;
03278     while (EOI == 0) {
03279         blocksize++;                                        /*increment blocksize counter*/
03280         track = nexttrack;                                    /*update the track variable*/
03281         sector = nextsector;                                /*update the track variable*/
03282         if (!D64BlockAllocate(track, sector)) {              /*claim the next block, update the BAM*/
03283             SetErrorCode(71,LED_ERROR);                        /*error: BAM is corrupt a flag has allready been cleared*/
03284             return(FALSE);                                    /*somebody or somthing has been messing with the BAM*/
03285         }
03286         fbpt = D64ReadFreeBlocksPerTrack(track) - 1;        /*decrement counter*/
03287         D64WriteFreeBlocksPerTrack(track, fbpt);             /*save new value to BAM*/
03288         if (!D64SeekFreeBlock(&nexttrack, &nextsector)) {      /*search for the next block location of the file to be saved*/
03289             SetErrorCode(72,LED_ERROR);                        /*error: disk or directory full*/
03290             return(FALSE);
03291         }
03292         /*the first two bytes of each block consist the 'track' and 'sector' of the next block*/
03293         RAM_buffer[0] =    nexttrack;                            /*track of next block*/
03294         RAM_buffer[1] = nextsector;                            /*sector of next block*/
03295 
03296         /*collect enough bytes to fill a block*/
03297         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*/
03298         for (lp=2; lp!=0; lp++) {
03299             SetErrorCode(0,LED_ON);                            /*unless we fail we will exit with no error*/
03300             RAM_buffer[lp] = IEC_receive(TRUE);                /*receive a byte and acknowledge with a frame handshake*/
03301             bytecounter++;
03302 // OutputToRS232();                    /*set standard output to RS232*/
03303 // printf(",%02x", RAM_buffer[lp]);    /*dump all received bytes to serial port*/
03304 // OutputToLCD();                        /*set standard output to LCD*/
03305             if (EOI == 1) {
03306                 RAM_buffer[0] =    0;                            /*there is no next block so the track value is an impossible one*/
03307                 RAM_buffer[1] = bytecounter;                /*there is no next block so the sector value is the position of the last byte*/
03308                 do {
03309                     RAM_buffer[bytecounter] = 0x00;            /*fill the remaining area with 0x00*/
03310                     bytecounter++;
03311                 } while (bytecounter!=0);
03312                 break;
03313             }
03314 
03315             if (lp == Blink_block)
03316                 SetErrorCode(0,LED_OFF);                    /*turn LED off, to create a small blink at every block*/
03317         }
03318 
03319         print_D64_TSB(track, sector, 0,blocksize);            /*print track, sector, remaining blocks and total number of blocks*/
03320         D64BlockWrite(track, sector);                        /*write the block to D64*/
03321     }
03322 
03323     /*write the filename to the directory*/
03324     if (!D64AddDirEntry(0x82,firsttrack,firstsector,command_string,blocksize,0,0,0,0,0)) {
03325         SetErrorCode(72,LED_ERROR);                            /*error: disk or directory full*/
03326         print_D64_TSB(track, sector, blocksize, blocksize);    /*print track, sector and remaining blocks and a fully filled bar*/
03327         return(FALSE);
03328     }
03329 
03330     SetErrorCode(0,LED_OFF);                                /*all is OK*/
03331     print_D64_TSB(track, sector, 0, blocksize);                /*print track, sector, remaining blocks creating a fully filled bar*/
03332     return(TRUE);
03333 }
03334 
03335 /*Copy a file within the D64, this requires the complete DOS handling !!!*/
03336 /*the filename is stored in command_string*/
03337 unsigned char CopyD64File(unsigned char trk, unsigned char sec, unsigned int filesizeinblocks) {
03338     unsigned int blocksrem;
03339     unsigned char fbpt, track, sector, nexttrack, nextsector;
03340 
03341     blocksrem = filesizeinblocks;
03342     SetErrorCode(0,LED_ON);                    /*unless we fail we will exit with no error*/
03343 
03344     /*search for the first block location of the new file to be saved*/
03345     if (!D64SeekFreeBlock(&track, &sector)) {
03346         SetErrorCode(72,LED_ERROR);                            /*error: disk or directory full*/
03347         return(FALSE);
03348     }
03349 
03350     /*check if there is enough room free on the disk for the required copy*/
03351     if (filesizeinblocks > D64LoadFreeBlocks()) {      /*read the number of free blocks from the D64 file*/
03352         SetErrorCode(72,LED_ERROR);                            /*error: disk or directory full*/
03353         return(FALSE);
03354     }
03355 
03356     /*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*/
03357     /*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 */
03358     D64AddDirEntry(0x82,track,sector,filename_string,filesizeinblocks,0,0,0,0,0);
03359 
03360     while (blocksrem--) {
03361         if (!D64BlockAllocate(track, sector)) {              /*claim the next block, update the BAM*/
03362             SetErrorCode(71,LED_ERROR);                        /*error: BAM is corrupt a flag has allready been cleared*/
03363             return(FALSE);                                    /*somebody or somthing has been messing with the BAM*/
03364         }
03365         fbpt = D64ReadFreeBlocksPerTrack(track) - 1;        /*decrement counter*/
03366         D64WriteFreeBlocksPerTrack(track, fbpt);             /*save new value to BAM*/
03367 
03368         /*search for the first block location of the new file to be saved*/
03369         if (!D64SeekFreeBlock(&nexttrack, &nextsector)) {
03370             SetErrorCode(72,LED_ERROR);                            /*error: disk or directory full*/
03371             return(FALSE);
03372         }
03373         print_D64_TSB(trk, sec, blocksrem, filesizeinblocks);    /*print track, sector and remaining blocks*/
03374         D64BlockRead(trk,sec);                                    /*this routine reads a block of a req. track-sector of a D64 into the RAM_buffer*/
03375         trk = RAM_buffer[0];                                    /*the next track to be read*/
03376         sec = RAM_buffer[1];                                    /*the next sector within that track*/
03377         RAM_buffer[0] =    nexttrack;                                /*track of next block*/
03378         RAM_buffer[1] = nextsector;                                /*sector of next block*/
03379         D64BlockWrite(track, sector);                            /*this routine write the contents of the RAM_buffer to the req. track-sector of the D64 file*/
03380 
03381         track = nexttrack;                                        /*for the next block, set the correct next track and sector*/
03382         sector = nextsector;
03383     }
03384 
03385     /*write last block of the file*/
03386     print_D64_TSB(trk, sec, blocksrem, filesizeinblocks);        /*print track, sector and remaining blocks*/
03387     D64BlockRead(trk,sec);                                        /*this routine reads a block of a req. track-sector of a D64 into the RAM_buffer*/
03388     D64BlockWrite(track, sector);                                /*this routine write the contents of the RAM_buffer to the req. track-sector of the D64 file*/
03389     SetErrorCode(0,LED_OFF);                                    /*all is OK*/
03390     return(TRUE);
03391 }
03392 
03393 
03394 /*this routine clears the entire block_buffer*/
03395 void Clear_block_buffer(void) {
03396     unsigned int lp;
03397 
03398     lp=0;
03399     do {
03400         block_buffer[lp] = 0x00;
03401         lp++;
03402     } while (lp<512);
03403 }
03404 
03405 /*this routine formats the currently selected D64 image so it can be used to save your programs/data to*/
03406 /*the abillity not being able to create a new file saves us the effort of implementing a lot of FAT related actions*/
03407 /*Attention: this command does not implement the user options (disk label,disk ID). This command is for firmware & media testing purposes only*/
03408 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*/
03409 
03410     unsigned int block_counter=0;
03411     unsigned char lp,lp2,tr,se;
03412 
03413     SetErrorCode(0,LED_ON);         /*unless we fail we will exit with no error*/
03414     print_D64_TSB(0,0,(341-block_counter),341);
03415 
03416     /*fill track 1 upto and including track 17 (all 21) sectors with 0x00*/
03417     /*each MMC/SD-card block = 512 bytes, each D64 block = 256 bytes     */
03418     /*17 tracks * 21 sectors = 357 D64 blocks or 178.5 MMC/SD-card blocks*/
03419     Clear_block_buffer();                            /*clear the block_buffer*/
03420     do {
03421         D64ConvertBlockToTrackSector((block_counter<<1), &tr, &se);
03422         print_D64_TSB(tr,se,(341-block_counter),341);
03423         FileWriteSector_X(&file, block_counter);
03424         block_counter++;
03425     } while (block_counter < 178);
03426 
03427     block_buffer[256+0] = 18;    /*track of next block*/
03428     block_buffer[256+1] = 18;    /*sector of next block*/
03429     block_buffer[256+2] = 65;
03430     block_buffer[256+3] =  0;
03431     block_buffer[256+4] = 0x15; /*number of sectors within track-1*/
03432     block_buffer[256+5] = 0xff;
03433     block_buffer[256+6] = 0xff;
03434     block_buffer[256+7] = 0x1f;
03435     block_buffer[256+8] = 0x15; /*number of sectors within track-2*/
03436     block_buffer[256+9] = 0xff;
03437     block_buffer[256+10] = 0xff;
03438     block_buffer[256+11] = 0x1f;
03439     block_buffer[256+12] = 0x15; /*number of sectors within track-3*/
03440     block_buffer[256+13] = 0xff;
03441     block_buffer[256+14] = 0xff;
03442     block_buffer[256+15] = 0x1f;
03443     block_buffer[256+16] = 0x15; /*number of sectors within track-4*/
03444     block_buffer[256+17] = 0xff;
03445     block_buffer[256+18] = 0xff;
03446     block_buffer[256+19] = 0x1f;
03447     block_buffer[256+20] = 0x15; /*number of sectors within track-5*/
03448     block_buffer[256+21] = 0xff;
03449     block_buffer[256+22] = 0xff;
03450     block_buffer[256+23] = 0x1f;
03451     block_buffer[256+24] = 0x15; /*number of sectors within track-6*/
03452     block_buffer[256+25] = 0xff;
03453     block_buffer[256+26] = 0xff;
03454     block_buffer[256+27] = 0x1f;
03455     block_buffer[256+28] = 0x15; /*number of sectors within track-7*/
03456     block_buffer[256+29] = 0xff;
03457     block_buffer[256+30] = 0xff;
03458     block_buffer[256+31] = 0x1f;
03459     block_buffer[256+32] = 0x15; /*number of sectors within track-8*/
03460     block_buffer[256+33] = 0xff;
03461     block_buffer[256+34] = 0xff;
03462     block_buffer[256+35] = 0x1f;
03463     block_buffer[256+36] = 0x15; /*number of sectors within track-9*/
03464     block_buffer[256+37] = 0xff;
03465     block_buffer[256+38] = 0xff;
03466     block_buffer[256+39] = 0x1f;
03467     block_buffer[256+40] = 0x15; /*number of sectors within track-10*/
03468     block_buffer[256+41] = 0xff;
03469     block_buffer[256+42] = 0xff;
03470     block_buffer[256+43] = 0x1f;
03471     block_buffer[256+44] = 0x15; /*number of sectors within track-11*/
03472     block_buffer[256+45] = 0xff;
03473     block_buffer[256+46] = 0xff;
03474     block_buffer[256+47] = 0x1f;
03475     block_buffer[256+48] = 0x15; /*number of sectors within track-12*/
03476     block_buffer[256+49] = 0xff;
03477     block_buffer[256+50] = 0xff;
03478     block_buffer[256+51] = 0x1f;
03479     block_buffer[256+52] = 0x15; /*number of sectors within track-13*/
03480     block_buffer[256+53] = 0xff;
03481     block_buffer[256+54] = 0xff;
03482     block_buffer[256+55] = 0x1f;
03483     block_buffer[256+56] = 0x15; /*number of sectors within track-14*/
03484     block_buffer[256+57] = 0xff;
03485     block_buffer[256+58] = 0xff;
03486     block_buffer[256+59] = 0x1f;
03487     block_buffer[256+60] = 0x15; /*number of sectors within track-15*/
03488     block_buffer[256+61] = 0xff;
03489     block_buffer[256+62] = 0xff;
03490     block_buffer[256+63] = 0x1f;
03491     block_buffer[256+64] = 0x15; /*number of sectors within track-16*/
03492     block_buffer[256+65] = 0xff;
03493     block_buffer[256+66] = 0xff;
03494     block_buffer[256+67] = 0x1f;
03495     block_buffer[256+68] = 0x15; /*number of sectors within track-17*/
03496     block_buffer[256+69] = 0xff;
03497     block_buffer[256+70] = 0xff;
03498     block_buffer[256+71] = 0x1f;
03499     block_buffer[256+72] = 0x11; /*number of sectors within track-18*/
03500     block_buffer[256+73] = 0xfc;
03501     block_buffer[256+74] = 0xff;
03502     block_buffer[256+75] = 0x07;
03503     block_buffer[256+76] = 0x13; /*number of sectors within track-19*/
03504     block_buffer[256+77] = 0xff;
03505     block_buffer[256+78] = 0xff;
03506     block_buffer[256+79] = 0x07;
03507     block_buffer[256+80] = 0x13; /*number of sectors within track-20*/
03508     block_buffer[256+81] = 0xff;
03509     block_buffer[256+82] = 0xff;
03510     block_buffer[256+83] = 0x07;
03511     block_buffer[256+84] = 0x13; /*number of sectors within track-21*/
03512     block_buffer[256+85] = 0xff;
03513     block_buffer[256+86] = 0xff;
03514     block_buffer[256+87] = 0x07;
03515     block_buffer[256+88] = 0x13; /*number of sectors within track-22*/
03516     block_buffer[256+89] = 0xff;
03517     block_buffer[256+90] = 0xff;
03518     block_buffer[256+91] = 0x07;
03519     block_buffer[256+92] = 0x13; /*number of sectors within track-23*/
03520     block_buffer[256+93] = 0xff;
03521     block_buffer[256+94] = 0xff;
03522     block_buffer[256+95] = 0x07;
03523     block_buffer[256+96] = 0x13; /*number of sectors within track-24*/
03524     block_buffer[256+97] = 0xff;
03525     block_buffer[256+98] = 0xff;
03526     block_buffer[256+99] = 0x07;
03527     block_buffer[256+100] = 0x12; /*number of sectors within track-25*/
03528     block_buffer[256+101] = 0xff;
03529     block_buffer[256+102] = 0xff;
03530     block_buffer[256+103] = 0x03;
03531     block_buffer[256+104] = 0x12; /*number of sectors within track-26*/
03532     block_buffer[256+105] = 0xff;
03533     block_buffer[256+106] = 0xff;
03534     block_buffer[256+107] = 0x03;
03535     block_buffer[256+108] = 0x12; /*number of sectors within track-27*/
03536     block_buffer[256+109] = 0xff;
03537     block_buffer[256+110] = 0xff;
03538     block_buffer[256+111] = 0x03;
03539     block_buffer[256+112] = 0x12; /*number of sectors within track-28*/
03540     block_buffer[256+113] = 0xff;
03541     block_buffer[256+114] = 0xff;
03542     block_buffer[256+115] = 0x03;
03543     block_buffer[256+116] = 0x12; /*number of sectors within track-29*/
03544     block_buffer[256+117] = 0xff;
03545     block_buffer[256+118] = 0xff;
03546     block_buffer[256+119] = 0x03;
03547     block_buffer[256+120] = 0x12; /*number of sectors within track-30*/
03548     block_buffer[256+121] = 0xff;
03549     block_buffer[256+122] = 0xff;
03550     block_buffer[256+123] = 0x03;
03551     block_buffer[256+124] = 0x11; /*number of sectors within track-31*/
03552     block_buffer[256+125] = 0xff;
03553     block_buffer[256+126] = 0xff;
03554     block_buffer[256+127] = 0x01;
03555     block_buffer[256+128] = 0x11; /*number of sectors within track-32*/
03556     block_buffer[256+129] = 0xff;
03557     block_buffer[256+130] = 0xff;
03558     block_buffer[256+131] = 0x01;
03559     block_buffer[256+132] = 0x11; /*number of sectors within track-33*/
03560     block_buffer[256+133] = 0xff;
03561     block_buffer[256+134] = 0xff;
03562     block_buffer[256+135] = 0x01;
03563     block_buffer[256+136] = 0x11; /*number of sectors within track-34*/
03564     block_buffer[256+137] = 0xff;
03565     block_buffer[256+138] = 0xff;
03566     block_buffer[256+139] = 0x01;
03567     block_buffer[256+140] = 0x11; /*number of sectors within track-35*/
03568     block_buffer[256+141] = 0xff;
03569     block_buffer[256+142] = 0xff;
03570     block_buffer[256+143] = 0x01;
03571 
03572     lp2=0;
03573     lp=144;
03574 
03575     while ((lp<160) && (diskname[lp2] != 0))       /*diskname*/
03576     {                                            /*--------*/
03577         block_buffer[256+lp] = diskname[lp2];    /*copy character*/
03578         lp2++;
03579         lp++;
03580     }
03581     while (lp<160) {
03582         block_buffer[256+lp] = 160;                /*fill unused locations with shifted spaces, default value*/
03583         lp++;
03584     }
03585 
03586     block_buffer[256+160] = 160;
03587     block_buffer[256+161] = 160;
03588 
03589     if (diskid[0] == 0)                            /*disk-ID*/
03590     {                                            /*-------*/
03591         block_buffer[256+162] = '0';            /*default value*/
03592         block_buffer[256+163] = '0';            /*default value*/
03593     } else {
03594         block_buffer[256+162] = diskid[0];        /*copy character*/
03595         if (diskid[1] == 0) {
03596             block_buffer[256+163] = 160;        /*default value*/
03597         } else {
03598             block_buffer[256+163] = diskid[1];    /*copy character*/
03599         }
03600     }
03601 
03602     block_buffer[256+164] = 160;
03603     block_buffer[256+165] = 50;    /*DOS VERSION*/
03604     block_buffer[256+166] = 65;    /*DOS VERSION*/
03605     block_buffer[256+167] = 160;
03606     block_buffer[256+168] = 160;
03607     block_buffer[256+169] = 160;
03608     block_buffer[256+170] = 160;
03609 
03610     lp = 171;
03611     while (lp != 0) {              /*fill remaining bytes from 171 up to and including 255 with 0x00*/
03612         block_buffer[256+lp] = 0x00;
03613         lp++;
03614     }
03615 
03616     D64ConvertBlockToTrackSector((block_counter<<1), &tr, &se);
03617     print_D64_TSB(tr,se,(341-block_counter),341);
03618     FileWriteSector_X(&file, block_counter);
03619     block_counter++;
03620 
03621     /*fill remaining tracks 18-1 to 35-16 with 0x00                      */
03622     /*each MMC/SD-card block = 512 bytes, each D64 block = 256 bytes     */
03623     Clear_block_buffer();                            /*clear the block_buffer*/
03624     do {
03625         D64ConvertBlockToTrackSector((block_counter<<1), &tr, &se);
03626         print_D64_TSB(tr,se,(341-block_counter),341);
03627         FileWriteSector_X(&file, block_counter);
03628         block_counter++;
03629     } while (block_counter < 342);
03630     SetErrorCode(0,LED_OFF);
03631 }
03632 
03633 /*this routine is to be used to handle the errorcode and the LED-blink-mode in an easy way*/
03634 void SetErrorCode(unsigned char error, unsigned char LEDmode) {
03635     /*the original 1541 used the LED to display the results of the power-on selftest*/
03636     /* No Blink       Kernal (E000-FFFF) ROM or 6522 VIA Failure */
03637     /* One Blink      6116 RAM Failure                           */
03638     /* Two Blinks     Possible Zero Page RAM Failure             */
03639     /* Three Blinks   DOS (C000-CFFF) ROM Failure                */
03640     /* Four Blinks    DOS (C000-CFFF) ROM Failure                */
03641     /* Five Blinks    6116 RAM Failure                           */
03642     /* Six Blinks     6116 RAM Failure                           */
03643     /* Seven Blinks   6116 RAM Failure                           */
03644     /* Eight Blinks   6116 RAM Failure                           */
03645     /*Note: at this moment the selftest (and it's blinking modes) is/are not supported (yet)*/
03646 
03647     if ((error == 0) && (error_code == 73)) {  /*when there is no error-73 to maintain (ROM version), change to the new error_code*/
03648         /*do not change the error_code, because there is no error and the code 73 must be preserved*/
03649     } else {
03650         if (error != error_code)            /*only update the screen when the error_code has changed*/
03651         {                                    /*because when there is no new info... there is no reason to print to the display what is allready there*/
03652             error_code = error;
03653             //        Lcd_XY_address(2,4);            /*if there is any printing to the display to be done, it must be done on line...*/
03654             printf("%02d",error_code);        /*show the error code*/
03655         }
03656 
03657         //    if ((error == 21) || (error == 62)) /*these error(s) create this sound (i.e. error 62 = file not found)*/
03658         //        PlaySample_HeadBangRattle();    /*play sample that suits this error situation*/
03659     }
03660 
03661     switch (LEDmode) {
03662         case LED_OFF: {
03663             //          TMR0ON = 0;                    /*switch timer-0 OFF*/
03664             LED_GREEN = 0;                /*switch LED-OFF*/
03665             LED_RED = 0;                /*switch LED-OFF*/
03666             break;
03667         }
03668 
03669         case LED_ON: {
03670 //            TMR0ON = 0;                    /*switch timer-0 OFF*/
03671             LED_GREEN = 1;                /*switch LED-ON*/
03672             LED_RED = 0;                /*switch LED-ON*/
03673             break;
03674         }
03675 
03676 
03677         case LED_ERROR: {
03678             Blink_mode = LED_ERROR;
03679             LED_status = 0;                /*status of the LED (0=OFF)*/
03680             //          TMR0H = 0xFF;                /*set registers to enter timer-o interrupt as quickly as possible*/
03681             //          TMR0L = 0xFF;
03682             //          TMR0ON = 1;                    /*switch timer-0 on*/
03683             break;
03684         }
03685 
03686         default: {
03687             //         TMR0ON = 0;                    /*switch timer-0 OFF*/
03688             LED_GREEN = 0;                /*switch LED-OFF*/
03689             LED_RED = 0;                /*switch LED-OFF*/
03690         }
03691     }
03692 }
03693 
03694 void SendErrorMessage(void) {
03695     EOI = FALSE;
03696     LED_GREEN = 1;                            /*drive LED-ON*/
03697     IEC_turnaround();                        /*we now SEND data to the bus so... make our device a talker*/
03698     IEC_send_number_as_ASCII(error_code);    /*send error-code*/
03699     IEC_send(0x2C);                            /*','*/
03700 
03701     switch (error_code) {
03702         case 0: {      /*OK (not an error*/
03703             IEC_send_string("OK");
03704             break;
03705         }
03706 
03707         case 1: {      /*files scratched (not an error)*/
03708             IEC_send_string("FILES SCRATCHED");
03709             break;
03710         }
03711 
03712         case 2:;    /*Unused error message (should be ingnored)*/
03713         case 3:;    /*Unused error message (should be ingnored)*/
03714         case 4:;    /*Unused error message (should be ingnored)*/
03715         case 5:;    /*Unused error message (should be ingnored)*/
03716         case 6:;    /*Unused error message (should be ingnored)*/
03717         case 7:;    /*Unused error message (should be ingnored)*/
03718         case 8:;    /*Unused error message (should be ingnored)*/
03719         case 9:;    /*Unused error message (should be ingnored)*/
03720         case 10:;    /*Unused error message (should be ingnored)*/
03721         case 11:;    /*Unused error message (should be ingnored)*/
03722         case 12:;    /*Unused error message (should be ingnored)*/
03723         case 13:;    /*Unused error message (should be ingnored)*/
03724         case 14:;    /*Unused error message (should be ingnored)*/
03725         case 15:;    /*Unused error message (should be ingnored)*/
03726         case 16:;    /*Unused error message (should be ingnored)*/
03727         case 17:;    /*Unused error message (should be ingnored)*/
03728         case 18:;    /*Unused error message (should be ingnored)*/
03729         case 19: {  /*Unused error message (should be ingnored)*/
03730             IEC_send_string("N/A");
03731             break;
03732         }
03733 
03734         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*/
03735         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.*/
03736         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.*/
03737         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.*/
03738         case 24:;    /*Write verify (on format)                    */
03739         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.*/
03740             IEC_send_string("READ ERROR");
03741             break;
03742         }
03743 
03744         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.*/
03745         case 28: {  /*Write error                                In actual fact, this error never occurs, but it is included for completeness.*/
03746             IEC_send_string("WRITE ERROR");
03747             break;
03748         }
03749 
03750         case 26: {  /*Write protect on                            Self explanatory. Remove the write-protect tab, and try again.*/
03751             IEC_send_string("WRITE PROTECT ON");
03752             break;
03753         }
03754 
03755         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.*/
03756             IEC_send_string("DISK ID MISMATCH");
03757             break;
03758         }
03759 
03760         case 30:;    /*general syntax error*/
03761         case 31:;    /*invalid command*/
03762         case 32:;    /*long line*/
03763         case 33:;    /*invalid fileSelectedFileName*/
03764         case 34:;    /*no file given*/
03765         case 39: {  /*command file not found*/
03766             IEC_send_string("SYNTAX ERROR");
03767             break;
03768         }
03769 
03770         case 50: {  /*record not present*/
03771             IEC_send_string("RECORD NOT PRESENT");
03772             break;
03773         }
03774 
03775         case 51: {  /*overflow in record*/
03776             IEC_send_string("OVERFLOW IN RECORD");
03777             break;
03778         }
03779 
03780         case 52: {  /*file too large*/
03781             IEC_send_string("FILE TOO LARGE");
03782             break;
03783         }
03784 
03785         case 60: {  /*File open for write*/
03786             IEC_send_string("WRITE FILE OPEN");
03787             break;
03788         }
03789 
03790         case 61: {  /*File not open*/
03791             IEC_send_string("FILE NOT OPEN");
03792             break;
03793         }
03794 
03795         case 62: {  /*File not found*/
03796             IEC_send_string("FILE NOT FOUND");
03797             break;
03798         }
03799 
03800         case 63: {  /*File exists*/
03801             IEC_send_string("FILE EXISTS");
03802             break;
03803         }
03804 
03805         case 64: {  /*File type mismatch*/
03806             IEC_send_string("FILE TYPE MISMATCH");
03807             break;
03808         }
03809 
03810         case 65: {  /*No block*/
03811             IEC_send_string("NO BLOCK");
03812             break;
03813         }
03814 
03815         case 66: {  /*Illegal track or sector*/
03816             IEC_send_string("ILLEGAL TRACK AND SECTOR");
03817             break;
03818         }
03819 
03820         case 67: {  /*Illegal system track or sector*/
03821             IEC_send_string("ILLEGAL SYSTEM T OR S");
03822             break;
03823         }
03824 
03825         case 70: {  /*No channels available*/
03826             IEC_send_string("NO CHANNEL");
03827             break;
03828         }
03829 
03830         case 71: {  /*Directory error*/
03831             IEC_send_string("DIRECTORY ERROR");
03832             break;
03833         }
03834 
03835         case 72: {  /*disk full or directory full*/
03836             IEC_send_string("DISK FULL");
03837             break;
03838         }
03839 
03840         case 73: {  /*DOS mismatch / Powerup message/write attempt with DOS mismatch*/
03841             IEC_send_string("V");
03842             IEC_send_number_as_ASCII(RELEASE_VERSION);
03843             IEC_send('-');
03844             IEC_send_number_as_ASCII(RELEASE_VERSION_SUB);
03845             IEC_send('-');
03846             IEC_send_number_as_ASCII(RELEASE_VERSION_SUB_SUB);
03847             break;
03848         }
03849 
03850         case 74: {  /*no disk in drive or no device 1 (8050 only)*/
03851             IEC_send_string("DRIVE NOT READY");
03852             break;
03853         }
03854 
03855         default: {
03856             IEC_send_string("ERROR UNKNOWN");
03857             break;
03858         }
03859     }
03860 
03861     DelayBigMs(50);                                    /*some small delay to give the computer time to process the string*/
03862     IEC_send(0x2C);                                    /*','*/
03863     if (error_code == 1)                            /*check for the FILES SCRATCHED-error*/
03864         IEC_send_number_as_ASCII(files_scratched);    /*last accessed track variable is replaced by the number of scratched files*/
03865     else
03866         IEC_send_number_as_ASCII(LastTrack);        /*last accessed track variable*/
03867     IEC_send(0x2C);                                    /*','*/
03868     IEC_send_number_as_ASCII(LastSector);            /*last accessed sector variable*/
03869     EOI = TRUE;                                        /*indicate the last byte*/
03870     IEC_send(0x0D);                                    /*CARRIAGE RETURN*/
03871     IEC_undoturnaround();                            /*were done talking towards the bus*/
03872     SetErrorCode(0,LED_OFF);                        /*error-code is 0, LED is OFF*/
03873 }
03874 /*****************************************************************************************************************/
03875 /*****************************************************************************************************************/
03876 /*****************************************************************************************************************/
03877 
03878 unsigned char ReadDeviceJumper(void) {
03879     if (JUMPER_J2 == 0)                    /*check the device number jumper to see what the req. device number should be*/
03880         return(8);
03881     else
03882         return(9);
03883 }
03884 
03885 /*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*/
03886 unsigned char ReadButtons(void) {
03887 
03888     return(FALSE);                            /*the 1541-III DTV, does NOT support the use of buttons*/
03889 
03890 }
03891 
03892 
03893 /*
03894 There's no shame in writing comments in your sourcecode.
03895 */