Description: C1541-III mbed edition
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, §or, &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, §or, &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, §or, &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, §or, &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, §or, &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, §or, &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, §or, &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, §or, &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, §or, &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, §or, &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, §or, &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, §or)) { 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, §or)) { 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 */
