diff --git a/floppy-emu-source-1.0L-F11/AVR/.settings/de.innot.avreclipse.core.prefs b/floppy-emu-source-1.0L-F11/AVR/.settings/de.innot.avreclipse.core.prefs index 1b9830c..3fda000 100644 --- a/floppy-emu-source-1.0L-F11/AVR/.settings/de.innot.avreclipse.core.prefs +++ b/floppy-emu-source-1.0L-F11/AVR/.settings/de.innot.avreclipse.core.prefs @@ -1,7 +1,8 @@ avrtarget/ClockFrequency=16000000 avrtarget/ExtRAMSize=0 avrtarget/ExtendedRAM=false -avrtarget/MCUType=atmega1284p +avrtarget/MCUType=atmega2560 avrtarget/UseEEPROM=false avrtarget/UseExtendedRAMforHeap=true +avrtarget/perConfig=false eclipse.preferences.version=1 diff --git a/floppy_emu_arduino/.settings/de.innot.avreclipse.core.prefs b/floppy_emu_arduino/.settings/de.innot.avreclipse.core.prefs index ea7b76a..1b9830c 100644 --- a/floppy_emu_arduino/.settings/de.innot.avreclipse.core.prefs +++ b/floppy_emu_arduino/.settings/de.innot.avreclipse.core.prefs @@ -4,5 +4,4 @@ avrtarget/ExtendedRAM=false avrtarget/MCUType=atmega1284p avrtarget/UseEEPROM=false avrtarget/UseExtendedRAMforHeap=true -avrtarget/perConfig=false eclipse.preferences.version=1 diff --git a/floppy_emu_arduino/.settings/org.eclipse.cdt.codan.core.prefs b/floppy_emu_arduino/.settings/org.eclipse.cdt.codan.core.prefs deleted file mode 100644 index 77386c2..0000000 --- a/floppy_emu_arduino/.settings/org.eclipse.cdt.codan.core.prefs +++ /dev/null @@ -1,67 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.cdt.codan.checkers.errnoreturn=Warning -org.eclipse.cdt.codan.checkers.errnoreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},implicit\=>false} -org.eclipse.cdt.codan.checkers.errreturnvalue=Error -org.eclipse.cdt.codan.checkers.errreturnvalue.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} -org.eclipse.cdt.codan.checkers.noreturn=Error -org.eclipse.cdt.codan.checkers.noreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},implicit\=>false} -org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation=Error -org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} -org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem=Error -org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} -org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem=Warning -org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} -org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem=Error -org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} -org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem=Warning -org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},no_break_comment\=>"no break",last_case_param\=>false,empty_case_param\=>false} -org.eclipse.cdt.codan.internal.checkers.CatchByReference=Warning -org.eclipse.cdt.codan.internal.checkers.CatchByReference.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},unknown\=>false,exceptions\=>()} -org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem=Error -org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} -org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization=Warning -org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},skip\=>true} -org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem=Error -org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} -org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem=Error -org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} -org.eclipse.cdt.codan.internal.checkers.InvalidArguments=Error -org.eclipse.cdt.codan.internal.checkers.InvalidArguments.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} -org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem=Error -org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} -org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem=Error -org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} -org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem=Error -org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} -org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem=Error -org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} -org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker=-Info -org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},pattern\=>"^[a-z]",macro\=>true,exceptions\=>()} -org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem=Warning -org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} -org.eclipse.cdt.codan.internal.checkers.OverloadProblem=Error -org.eclipse.cdt.codan.internal.checkers.OverloadProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} -org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem=Error -org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} -org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem=Error -org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} -org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem=-Warning -org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} -org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem=-Warning -org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} -org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem=Warning -org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true,exceptions\=>()} -org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem=Warning -org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},paramNot\=>false} -org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem=Warning -org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},else\=>false,afterelse\=>false} -org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem=Error -org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} -org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem=Warning -org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true} -org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem=Warning -org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true} -org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem=Warning -org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true,exceptions\=>("@(\#)","$Id")} -org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem=Error -org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}} diff --git a/floppy_emu_arduino/.settings/org.eclipse.cdt.core.prefs b/floppy_emu_arduino/.settings/org.eclipse.cdt.core.prefs index 6fd874b..397f7cb 100644 --- a/floppy_emu_arduino/.settings/org.eclipse.cdt.core.prefs +++ b/floppy_emu_arduino/.settings/org.eclipse.cdt.core.prefs @@ -1,21 +1,16 @@ eclipse.preferences.version=1 -environment/project/de.innot.avreclipse.configuration.app.debug.225132627/LANG/delimiter=\: -environment/project/de.innot.avreclipse.configuration.app.debug.225132627/LANG/operation=append -environment/project/de.innot.avreclipse.configuration.app.debug.225132627/LANG/value=en-US -environment/project/de.innot.avreclipse.configuration.app.debug.225132627/append=true -environment/project/de.innot.avreclipse.configuration.app.debug.225132627/appendContributed=true -environment/project/de.innot.avreclipse.configuration.app.debug.276225876/LANG/delimiter=\: -environment/project/de.innot.avreclipse.configuration.app.debug.276225876/LANG/operation=append -environment/project/de.innot.avreclipse.configuration.app.debug.276225876/LANG/value=en-US -environment/project/de.innot.avreclipse.configuration.app.debug.276225876/append=true -environment/project/de.innot.avreclipse.configuration.app.debug.276225876/appendContributed=true -environment/project/de.innot.avreclipse.configuration.app.release.472085903/LANG/delimiter=\: -environment/project/de.innot.avreclipse.configuration.app.release.472085903/LANG/operation=append -environment/project/de.innot.avreclipse.configuration.app.release.472085903/LANG/value=en-US -environment/project/de.innot.avreclipse.configuration.app.release.472085903/append=true -environment/project/de.innot.avreclipse.configuration.app.release.472085903/appendContributed=true -environment/project/de.innot.avreclipse.configuration.app.release.924927447/LANG/delimiter=\: -environment/project/de.innot.avreclipse.configuration.app.release.924927447/LANG/operation=append -environment/project/de.innot.avreclipse.configuration.app.release.924927447/LANG/value=en-US -environment/project/de.innot.avreclipse.configuration.app.release.924927447/append=true -environment/project/de.innot.avreclipse.configuration.app.release.924927447/appendContributed=true +environment/project/de.innot.avreclipse.configuration.app.debug.1718737082/LANG/delimiter=\: +environment/project/de.innot.avreclipse.configuration.app.debug.1718737082/LANG/operation=append +environment/project/de.innot.avreclipse.configuration.app.debug.1718737082/LANG/value=en-US +environment/project/de.innot.avreclipse.configuration.app.debug.1718737082/append=true +environment/project/de.innot.avreclipse.configuration.app.debug.1718737082/appendContributed=true +environment/project/de.innot.avreclipse.configuration.app.debug.674828633/LANG/delimiter=\: +environment/project/de.innot.avreclipse.configuration.app.debug.674828633/LANG/operation=append +environment/project/de.innot.avreclipse.configuration.app.debug.674828633/LANG/value=en-US +environment/project/de.innot.avreclipse.configuration.app.debug.674828633/append=true +environment/project/de.innot.avreclipse.configuration.app.debug.674828633/appendContributed=true +environment/project/de.innot.avreclipse.configuration.app.release.1024470171/LANG/delimiter=\: +environment/project/de.innot.avreclipse.configuration.app.release.1024470171/LANG/operation=append +environment/project/de.innot.avreclipse.configuration.app.release.1024470171/LANG/value=en-US +environment/project/de.innot.avreclipse.configuration.app.release.1024470171/append=true +environment/project/de.innot.avreclipse.configuration.app.release.1024470171/appendContributed=true diff --git a/floppy_emu_arduino/cardtest/cardtest.cpp b/floppy_emu_arduino/cardtest.cpp similarity index 96% rename from floppy_emu_arduino/cardtest/cardtest.cpp rename to floppy_emu_arduino/cardtest.cpp index c08effc..9e2054d 100755 --- a/floppy_emu_arduino/cardtest/cardtest.cpp +++ b/floppy_emu_arduino/cardtest.cpp @@ -38,7 +38,6 @@ #define PSTR(s) (__extension__({static prog_char __c[] PROGMEM = (s); &__c[0];})) #endif - #define STATUS_LED_PORT B #define STATUS_LED_PIN 3 diff --git a/floppy_emu_arduino/cardtest/cardtest.h b/floppy_emu_arduino/cardtest.h similarity index 100% rename from floppy_emu_arduino/cardtest/cardtest.h rename to floppy_emu_arduino/cardtest.h diff --git a/floppy_emu_arduino/diskmenu.cpp b/floppy_emu_arduino/diskmenu.cpp old mode 100644 new mode 100755 index 0f5780e..046b09a --- a/floppy_emu_arduino/diskmenu.cpp +++ b/floppy_emu_arduino/diskmenu.cpp @@ -1,368 +1,368 @@ -/* - Floppy Emu, copyright 2013 Steve Chamberlin, "Big Mess o' Wires". All rights reserved. - - Floppy Emu is licensed under a Creative Commons Attribution-NonCommercial 3.0 Unported - license. (CC BY-NC 3.0) The terms of the license may be viewed at - http://creativecommons.org/licenses/by-nc/3.0/ - - Based on a work at http://www.bigmessowires.com/macintosh-floppy-emu/ - - Permissions beyond the scope of this license may be available at www.bigmessowires.com - or from mailto:steve@bigmessowires.com. -*/ - -#include -#include -#include -#include -#include -#include -#include - -#include "diskmenu.h" -#include "SdFat.h" -#include "SdBaseFile.h" -#include "noklcd.h" - -#define SECTORBUF_SIZE (23 * 512) // use the 24th buffer for directory breadcrumbs -extern uint8_t sectorBuf[24][512]; -extern uint8_t extraBuf[512]; - -typedef struct FileEntry -{ - char longName[FILENAME_LEN+1]; - char shortName[SHORTFILENAME_LEN+1]; - eImageType imageFileType; -} FileEntry; - -bool dirLfnNext(SdFat& sd, dir_t& dir, char* lfn) -{ - uint8_t offset[] = {1, 3, 5, 7, 9, 14, 16, 18, 20, 22, 24, 28, 30}; - uint8_t lfnIn = 130; - uint8_t i; - uint8_t ndir=0; - uint8_t sum; - uint8_t test=0; - bool haveLong = false; - - while( sd.vwd()->read( &dir, 32 ) == 32 ) - { - if( DIR_IS_LONG_NAME( &dir ) ) - { - if( ! haveLong ) - { - if(( dir.name[0] & 0XE0 ) != 0X40 ) - continue; - ndir = dir.name[0] & 0X1F; - test = dir.creationTimeTenths; - haveLong = true; - lfnIn = 130; - lfn[ lfnIn ] = 0; - } - else if( dir.name[0] != --ndir || test != dir.creationTimeTenths ) - { - haveLong = false; - continue; - } - char *p = (char*) & dir; - if( lfnIn > 0 ) - { - lfnIn -= 13; - for( i = 0; i < 13; i++ ) - lfn[lfnIn + i] = p[offset[i]]; - } - } - else if( DIR_IS_FILE_OR_SUBDIR( &dir ) - && dir.name[0] != DIR_NAME_DELETED - && dir.name[0] != DIR_NAME_FREE - && dir.name[0] != '.') - { - if( haveLong ) - { - for( sum = i = 0; i < 11; i++ ) - sum = (((sum & 1) << 7) | ((sum & 0xfe) >> 1)) + dir.name[i]; - if( sum != test || ndir != 1 ) - haveLong = false; - } - if( haveLong ) - { - for( i = 0; lfnIn + i <= 130 ; i++ ) - lfn[i] = lfn[lfnIn + i]; - return true; - } - // else if( dir.reservedNT ) - // return "Reserved NT"; - else - { - SdBaseFile::dirName( dir, lfn ); - return true; - } - } - else - { - if( dir.name[0] == DIR_NAME_FREE ) - break; - haveLong = false; - } - } - lfn[ 0 ] = 0; - return false; -} - -eImageType DiskImageFileType(dir_t& dir, const char *filename) -{ - if (filename[0] == '.') - return DISK_IMAGE_NONE; - - if (DIR_IS_SUBDIR(&dir)) - return DISK_IMAGE_DIRECTORY; - - if (!DIR_IS_FILE(&dir)) - return DISK_IMAGE_NONE; - - uint32_t size = dir.fileSize; - - if (size == (unsigned long)1024 * 400) - return DISK_IMAGE_400K; - else if (size == (unsigned long)1024 * 800) - return DISK_IMAGE_800K; - else if (size == (unsigned long)1024 * 1440) - return DISK_IMAGE_1440K; - else if (size > (unsigned long)1024 * 400 && - size < (unsigned long)1024 * 1500) - { - // get the 8.3 filename - char shortName[SHORTFILENAME_LEN+1]; - SdBaseFile::dirName(dir, shortName); - - // read the first sector of the file - SdBaseFile f; - if (f.open(shortName, O_RDONLY)) - { - f.read(extraBuf, 512); - f.close(); - - // is it a DiskCopy 4.2 image? - if (extraBuf[0x52] == 0x01 && - extraBuf[0x53] == 0x00) - { - size = ((unsigned long)extraBuf[0x41] * 65536 + (unsigned long)extraBuf[0x42] * 256 + (unsigned long)extraBuf[0x43]) / 1024; - - if (size == 400) - return DISK_IMAGE_DISKCOPY_400K; - else if (size == 800) - return DISK_IMAGE_DISKCOPY_800K; - else if (size == 1440) - return DISK_IMAGE_DISKCOPY_1440K; - } - } - } - - return DISK_IMAGE_NONE; -} - -uint16_t diskMenuEntryCount; -uint16_t diskMenuOffset = 0; -uint16_t diskMenuSelection = 0; -char selectedFile[FILENAME_LEN+1]; -char selectedLongFile[FILENAME_LEN+1]; -eImageType selectedFileType; -uint8_t subdirDepth = 0; - -#define LONGFILENAME_LEN 130 - -void InitDiskMenu(SdFat& sd) -{ - dir_t dir; - char name[LONGFILENAME_LEN+1]; - - diskMenuEntryCount = 0; - - // use the sector buffers to hold the filenames - uint16_t maxEntries = SECTORBUF_SIZE / sizeof(FileEntry); - FileEntry* pFileEntries = (FileEntry*)sectorBuf; - - sd.vwd()->rewind(); - while (dirLfnNext(sd, dir, name) && diskMenuEntryCount < maxEntries) - { - eImageType imageType; - - if ((imageType = DiskImageFileType(dir, name)) != DISK_IMAGE_NONE) - { - strncpy(pFileEntries[diskMenuEntryCount].longName, name, FILENAME_LEN+1); - SdBaseFile::dirName(dir, pFileEntries[diskMenuEntryCount].shortName); - pFileEntries[diskMenuEntryCount].imageFileType = imageType; - diskMenuEntryCount++; - } - } - - // add up directory, if not at the root - if (!sd.vwd()->isRoot()) - { - strncpy(pFileEntries[diskMenuEntryCount].longName, "..", FILENAME_LEN+1); - strncpy(pFileEntries[diskMenuEntryCount].shortName, "..", SHORTFILENAME_LEN+1); - pFileEntries[diskMenuEntryCount].imageFileType = DISK_IMAGE_UP_DIRECTORY; - diskMenuEntryCount++; - } - - char file1[FILENAME_LEN+1], file2[FILENAME_LEN+1], temp[FILENAME_LEN+1]; - eImageType tempType; - - // sort the names by longname - for (uint16_t i=0; i file2, swap them - if (diff > 0) - { - strncpy(temp, pFileEntries[i].longName, FILENAME_LEN+1); - strncpy(pFileEntries[i].longName, pFileEntries[j].longName, FILENAME_LEN+1); - strncpy(pFileEntries[j].longName, temp, FILENAME_LEN+1); - - strncpy(temp, pFileEntries[i].shortName, SHORTFILENAME_LEN+1); - strncpy(pFileEntries[i].shortName, pFileEntries[j].shortName, SHORTFILENAME_LEN+1); - strncpy(pFileEntries[j].shortName, temp, SHORTFILENAME_LEN+1); - - tempType = pFileEntries[i].imageFileType; - pFileEntries[i].imageFileType = pFileEntries[j].imageFileType; - pFileEntries[j].imageFileType = tempType; - } - } - } -} - -void DrawDiskMenu(SdFat& sd) -{ - // scroll menu if necessary - if (diskMenuSelection < diskMenuOffset) - diskMenuOffset = diskMenuSelection; - if (diskMenuSelection > diskMenuOffset+4) - diskMenuOffset = diskMenuSelection-4; - - LcdGoto(0,0); - LcdWrite(LCD_DATA, 0x7F); - for (int i=0; i<19; i++) - LcdWrite(LCD_DATA, 0x40); - - LcdTinyStringFramed("Select Disk"); - - for (int i=0; i<19; i++) - LcdWrite(LCD_DATA, 0x40); - LcdWrite(LCD_DATA, 0x7F); - - if (diskMenuEntryCount == 0) - { - LcdGoto(0, 1); - LcdTinyString("no image files found", TEXT_NORMAL); - } - else - { - FileEntry* pFileEntries = (FileEntry*)sectorBuf; - - int row = 0; - for (uint16_t i=diskMenuOffset; i= barStart && y <= barEnd) - b = 0x80 | (b >> 1); - else - b = (b >> 1); - } - - LcdWrite(LCD_DATA, b); - } - } - - // prevent moving selection past end of list - if (diskMenuSelection >= diskMenuOffset + row) - { - diskMenuSelection = diskMenuOffset + row - 1; - if (row == 4 && diskMenuOffset > 0) - { - diskMenuOffset--; // scroll backwards - } - DrawDiskMenu(sd); // draw again - } - } -} +/* + Floppy Emu, copyright 2013 Steve Chamberlin, "Big Mess o' Wires". All rights reserved. + + Floppy Emu is licensed under a Creative Commons Attribution-NonCommercial 3.0 Unported + license. (CC BY-NC 3.0) The terms of the license may be viewed at + http://creativecommons.org/licenses/by-nc/3.0/ + + Based on a work at http://www.bigmessowires.com/macintosh-floppy-emu/ + + Permissions beyond the scope of this license may be available at www.bigmessowires.com + or from mailto:steve@bigmessowires.com. +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include "diskmenu.h" +#include "SdFat.h" +#include "SdBaseFile.h" +#include "noklcd.h" + +#define SECTORBUF_SIZE (23 * 512) // use the 24th buffer for directory breadcrumbs +extern uint8_t sectorBuf[24][512]; +extern uint8_t extraBuf[512]; + +typedef struct FileEntry +{ + char longName[FILENAME_LEN+1]; + char shortName[SHORTFILENAME_LEN+1]; + eImageType imageFileType; +} FileEntry; + +bool dirLfnNext(SdFat& sd, dir_t& dir, char* lfn) +{ + uint8_t offset[] = {1, 3, 5, 7, 9, 14, 16, 18, 20, 22, 24, 28, 30}; + uint8_t lfnIn = 130; + uint8_t i; + uint8_t ndir=0; + uint8_t sum; + uint8_t test=0; + bool haveLong = false; + + while( sd.vwd()->read( &dir, 32 ) == 32 ) + { + if( DIR_IS_LONG_NAME( &dir ) ) + { + if( ! haveLong ) + { + if(( dir.name[0] & 0XE0 ) != 0X40 ) + continue; + ndir = dir.name[0] & 0X1F; + test = dir.creationTimeTenths; + haveLong = true; + lfnIn = 130; + lfn[ lfnIn ] = 0; + } + else if( dir.name[0] != --ndir || test != dir.creationTimeTenths ) + { + haveLong = false; + continue; + } + char *p = (char*) & dir; + if( lfnIn > 0 ) + { + lfnIn -= 13; + for( i = 0; i < 13; i++ ) + lfn[lfnIn + i] = p[offset[i]]; + } + } + else if( DIR_IS_FILE_OR_SUBDIR( &dir ) + && dir.name[0] != DIR_NAME_DELETED + && dir.name[0] != DIR_NAME_FREE + && dir.name[0] != '.') + { + if( haveLong ) + { + for( sum = i = 0; i < 11; i++ ) + sum = (((sum & 1) << 7) | ((sum & 0xfe) >> 1)) + dir.name[i]; + if( sum != test || ndir != 1 ) + haveLong = false; + } + if( haveLong ) + { + for( i = 0; lfnIn + i <= 130 ; i++ ) + lfn[i] = lfn[lfnIn + i]; + return true; + } + // else if( dir.reservedNT ) + // return "Reserved NT"; + else + { + SdBaseFile::dirName( dir, lfn ); + return true; + } + } + else + { + if( dir.name[0] == DIR_NAME_FREE ) + break; + haveLong = false; + } + } + lfn[ 0 ] = 0; + return false; +} + +eImageType DiskImageFileType(dir_t& dir, const char *filename) +{ + if (filename[0] == '.') + return DISK_IMAGE_NONE; + + if (DIR_IS_SUBDIR(&dir)) + return DISK_IMAGE_DIRECTORY; + + if (!DIR_IS_FILE(&dir)) + return DISK_IMAGE_NONE; + + uint32_t size = dir.fileSize; + + if (size == (unsigned long)1024 * 400) + return DISK_IMAGE_400K; + else if (size == (unsigned long)1024 * 800) + return DISK_IMAGE_800K; + else if (size == (unsigned long)1024 * 1440) + return DISK_IMAGE_1440K; + else if (size > (unsigned long)1024 * 400 && + size < (unsigned long)1024 * 1500) + { + // get the 8.3 filename + char shortName[SHORTFILENAME_LEN+1]; + SdBaseFile::dirName(dir, shortName); + + // read the first sector of the file + SdBaseFile f; + if (f.open(shortName, O_RDONLY)) + { + f.read(extraBuf, 512); + f.close(); + + // is it a DiskCopy 4.2 image? + if (extraBuf[0x52] == 0x01 && + extraBuf[0x53] == 0x00) + { + size = ((unsigned long)extraBuf[0x41] * 65536 + (unsigned long)extraBuf[0x42] * 256 + (unsigned long)extraBuf[0x43]) / 1024; + + if (size == 400) + return DISK_IMAGE_DISKCOPY_400K; + else if (size == 800) + return DISK_IMAGE_DISKCOPY_800K; + else if (size == 1440) + return DISK_IMAGE_DISKCOPY_1440K; + } + } + } + + return DISK_IMAGE_NONE; +} + +uint16_t diskMenuEntryCount; +uint16_t diskMenuOffset = 0; +uint16_t diskMenuSelection = 0; +char selectedFile[FILENAME_LEN+1]; +char selectedLongFile[FILENAME_LEN+1]; +eImageType selectedFileType; +uint8_t subdirDepth = 0; + +#define LONGFILENAME_LEN 130 + +void InitDiskMenu(SdFat& sd) +{ + dir_t dir; + char name[LONGFILENAME_LEN+1]; + + diskMenuEntryCount = 0; + + // use the sector buffers to hold the filenames + uint16_t maxEntries = SECTORBUF_SIZE / sizeof(FileEntry); + FileEntry* pFileEntries = (FileEntry*)sectorBuf; + + sd.vwd()->rewind(); + while (dirLfnNext(sd, dir, name) && diskMenuEntryCount < maxEntries) + { + eImageType imageType; + + if ((imageType = DiskImageFileType(dir, name)) != DISK_IMAGE_NONE) + { + strncpy(pFileEntries[diskMenuEntryCount].longName, name, FILENAME_LEN+1); + SdBaseFile::dirName(dir, pFileEntries[diskMenuEntryCount].shortName); + pFileEntries[diskMenuEntryCount].imageFileType = imageType; + diskMenuEntryCount++; + } + } + + // add up directory, if not at the root + if (!sd.vwd()->isRoot()) + { + strncpy(pFileEntries[diskMenuEntryCount].longName, "..", FILENAME_LEN+1); + strncpy(pFileEntries[diskMenuEntryCount].shortName, "..", SHORTFILENAME_LEN+1); + pFileEntries[diskMenuEntryCount].imageFileType = DISK_IMAGE_UP_DIRECTORY; + diskMenuEntryCount++; + } + + char file1[FILENAME_LEN+1], file2[FILENAME_LEN+1], temp[FILENAME_LEN+1]; + eImageType tempType; + + // sort the names by longname + for (uint16_t i=0; i file2, swap them + if (diff > 0) + { + strncpy(temp, pFileEntries[i].longName, FILENAME_LEN+1); + strncpy(pFileEntries[i].longName, pFileEntries[j].longName, FILENAME_LEN+1); + strncpy(pFileEntries[j].longName, temp, FILENAME_LEN+1); + + strncpy(temp, pFileEntries[i].shortName, SHORTFILENAME_LEN+1); + strncpy(pFileEntries[i].shortName, pFileEntries[j].shortName, SHORTFILENAME_LEN+1); + strncpy(pFileEntries[j].shortName, temp, SHORTFILENAME_LEN+1); + + tempType = pFileEntries[i].imageFileType; + pFileEntries[i].imageFileType = pFileEntries[j].imageFileType; + pFileEntries[j].imageFileType = tempType; + } + } + } +} + +void DrawDiskMenu(SdFat& sd) +{ + // scroll menu if necessary + if (diskMenuSelection < diskMenuOffset) + diskMenuOffset = diskMenuSelection; + if (diskMenuSelection > diskMenuOffset+4) + diskMenuOffset = diskMenuSelection-4; + + LcdGoto(0,0); + LcdWrite(LCD_DATA, 0x7F); + for (int i=0; i<19; i++) + LcdWrite(LCD_DATA, 0x40); + + LcdTinyStringFramed("Select Disk"); + + for (int i=0; i<19; i++) + LcdWrite(LCD_DATA, 0x40); + LcdWrite(LCD_DATA, 0x7F); + + if (diskMenuEntryCount == 0) + { + LcdGoto(0, 1); + LcdTinyString("no image files found", TEXT_NORMAL); + } + else + { + FileEntry* pFileEntries = (FileEntry*)sectorBuf; + + int row = 0; + for (uint16_t i=diskMenuOffset; i= barStart && y <= barEnd) + b = 0x80 | (b >> 1); + else + b = (b >> 1); + } + + LcdWrite(LCD_DATA, b); + } + } + + // prevent moving selection past end of list + if (diskMenuSelection >= diskMenuOffset + row) + { + diskMenuSelection = diskMenuOffset + row - 1; + if (row == 4 && diskMenuOffset > 0) + { + diskMenuOffset--; // scroll backwards + } + DrawDiskMenu(sd); // draw again + } + } +} diff --git a/floppy_emu_arduino/floppy_emu_arduino.ino b/floppy_emu_arduino/floppy_emu_arduino.ino deleted file mode 100644 index 16803eb..0000000 --- a/floppy_emu_arduino/floppy_emu_arduino.ino +++ /dev/null @@ -1,471 +0,0 @@ -/* - * floppy_emu_arduino.ino - * - * Created on: 2014/07/12 - * Author: sin - */ - -#include - -#include -#include - -#include "portmacros.h" - -#include "millitimer.h" -#include "diskmenu.h" -#include "noklcd.h" - -#include "floppyemu.h" - - SdFat sd; - -void setup() { - millitimerInit(); - ResetDiskState(); - - ShowVersion(); - - LcdClear(); - - sei(); - _delay_ms(100); // wait for pending interrupts?? - - millitimerOn(); - _delay_ms(100); // wait for pending interrupts?? - - // if select and next are both held down, enter contrast adjust mode - if (bit_is_set(PIN(PREV_BUTTON_PORT), PREV_BUTTON_PIN) && - bit_is_clear(PIN(NEXT_BUTTON_PORT), NEXT_BUTTON_PIN) && - bit_is_clear(PIN(SELECT_BUTTON_PORT),SELECT_BUTTON_PIN)) - { - AdjustContrast(); - } - - //SdFat sd; - if (!sd.init(SPI_FULL_SPEED)) - { - snprintf(textBuf, TEXTBUF_SIZE, "SD card error %d:%d", sd.card()->errorCode(), sd.card()->errorData()); - error(textBuf); - } - - millitimerOff(); - - // if prev and next are both held down, enter firmware update mode - if (bit_is_clear(PIN(PREV_BUTTON_PORT), PREV_BUTTON_PIN) && - bit_is_clear(PIN(NEXT_BUTTON_PORT), NEXT_BUTTON_PIN) && - bit_is_set(PIN(SELECT_BUTTON_PORT),SELECT_BUTTON_PIN)) - { - PromptForFirmwareUpdate(); - } - - InitDiskMenu(sd); - DrawDiskMenu(sd); - -} - - -// main loop -void loop() { - if (writeError) - { - // report error encounted in the interrupt routine - error(textBuf); - } - - cli(); - uint8_t trackNumber = currentTrack; // save track in a local var, since currentTrack is volatile - uint8_t sideNumber = currentSide; // save side in a local var, since currentSide is volatile - restartDisk = false; - sei(); - - if (diskInserted) - { - // show the current track and side - snprintf(textBuf, TEXTBUF_SIZE, "%02d", trackNumber); - LcdGoto(24,4); - LcdTinyString(textBuf, TEXT_NORMAL); - snprintf(textBuf, TEXTBUF_SIZE, "%d ", sideNumber); - LcdGoto(56,4); - LcdTinyString(textBuf, TEXT_NORMAL); - - // sync RAM buffer with SD card when switching tracks, or also when switching sides for mfmMode - if (prevTrack != trackNumber || (mfmMode && (prevSide != sideNumber))) - { - // write any dirty sectors from the previous track/side back to the SD card - FlushDirtySectors(sd, prevTrack); - prevTrack = trackNumber; - prevSide = sideNumber; - - // Also mark all the buffers on this track as invalid, since they don't contain valid data for the new track. - for (uint8_t i=0; i= trackLen) - currentSector = 0; - - bool prevMotorOn = !bit_is_clear(PIN(CPLD_STEP_DIR_MOTOR_ON_PORT), CPLD_STEP_DIR_MOTOR_ON_PIN); - - while (true) - { - // check for disk eject - if (bit_is_set(PIN(CPLD_EJECT_REQ_PORT), CPLD_EJECT_REQ_PIN)) - { - PORT(CPLD_RD_READY_TK0_PORT) &= ~(1<readBlock(blockToRead, sectorBuf[bufferNumber])) - error("SD read error R"); - } - - millitimerOff(); - - bufferState[bufferNumber] |= BUFFER_DATA_VALID; - bufferState[bufferNumber] &= ~BUFFER_LOCKED; - } - - if (currentSector == 0) - { - if (motorOn) - { - // toggle LED during drive activity - PORT(STATUS_LED_PORT) ^= (1< 1) - writeDisplayTimer--; - } - - // "Flutter" the drive's TACH speed slightly, every time we pass sector 0 (about every 100-150ms). This avoids a bug - // in P_Sony_MakeSpdTbl in the 64K ROM (used in the Mac 128K and Mac 512K) where - // the Mac will crash if two successive TACH measurements see the exact same speed. - tachFlutter += 25; - if (tachFlutter >= 125) - tachFlutter = 0; - - // Set the timeout. OC1A will toggle after this many counts. New timeout threshold won't take effect until the next timeout. - OCR1A = driveTachHalfPeriod - tachFlutter; - } - - if (mfmMode) - { - // insert sector-to-sector gap bytes - for (uint8_t i=0; i<50; i++) - { - SendMFMAndCheckRestart(0x4E); - } - - // insert sync bytes - for (uint8_t i=0; i<12; i++) - { - SendMFMAndCheckRestart(0x00); - } - - // send the address block - crc = 0xFFFF; // reset CRC - SendMFMSync(); - SendMFMSync(); - SendMFMSync(); - SendMFMAndCheckRestart(0xFE); - SendMFMAndCheckRestart(trackNumber); - SendMFMAndCheckRestart(sideNumber); - SendMFMAndCheckRestart(currentSector+1); // MFM sector numbers are 1-based - SendMFMAndCheckRestart(2); // size = 128 * 2^N bytes, so 2 means 512 - uint8_t crc0 = (crc >> 8) & 0xFF; - uint8_t crc1 = crc & 0xFF; - SendMFMAndCheckRestart(crc0); - SendMFMAndCheckRestart(crc1); - - // insert Address to Data gap bytes - for (uint8_t i=0; i<22; i++) - { - SendMFMAndCheckRestart(0x4E); - } - - // insert sync bytes - for (uint8_t i=0; i<12; i++) - { - SendMFMAndCheckRestart(0x00); - } - - // send the data block - crc = 0xFFFF; // reset CRC - SendMFMSync(); - SendMFMSync(); - SendMFMSync(); - SendMFMAndCheckRestart(0xFB); - - for (uint16_t i=0; i> 8) & 0xFF; - crc1 = crc & 0xFF; - SendMFMAndCheckRestart(crc0); - SendMFMAndCheckRestart(crc1); - } - else - { - // ensure a short gap between sectors - otherwise once they're all cached, one sector will appear - // to immediately follow another on disk, which may cause problems for the Mac. - // Bad voodoo here: - // 1. In the Finder StuffIt copy test that sometimes dies after the first 18 tracks, the length of delay here - // seems to affect what track it will freeze on. - // 2. With a longer delay here, the first ~10 sectors of copying seem to have fewer or no "long writes". - // 3. Depending on the delay here, the Transcend 2GB SD card sometimes gets "writeStop fail" when saving tracks. - for (uint16_t i=0; i> 6)); - uint8_t checksum = (uint8_t)((trackLow ^ currentSector ^ trackHigh ^ format) & 0x3F); - - SendByteAndCheckRestart(0xD5); - SendByteAndCheckRestart(0xAA); - SendByteAndCheckRestart(0x96); - SendByteAndCheckRestart(pgm_read_byte(&sony_to_disk_byte[trackLow])); - SendByteAndCheckRestart(pgm_read_byte(&sony_to_disk_byte[currentSector])); - SendByteAndCheckRestart(pgm_read_byte(&sony_to_disk_byte[trackHigh])); - SendByteAndCheckRestart(pgm_read_byte(&sony_to_disk_byte[format])); - SendByteAndCheckRestart(pgm_read_byte(&sony_to_disk_byte[checksum])); - SendByteAndCheckRestart(0xDE); - SendByteAndCheckRestart(0xAA); - - // insert sync bytes between the address and data blocks - for (uint8_t i=0; i 0) - { - diskMenuSelection--; - DrawDiskMenu(sd); - _delay_ms(200); - } - } - else if (bit_is_clear(PIN(NEXT_BUTTON_PORT), NEXT_BUTTON_PIN)) - { - diskMenuSelection++; - DrawDiskMenu(sd); - _delay_ms(200); - } - else if (bit_is_clear(PIN(SELECT_BUTTON_PORT), SELECT_BUTTON_PIN)) - { - if (selectedFileType == DISK_IMAGE_DIRECTORY) - { - // remember where we came from, so we can get back later - char* pSubdirName = ((char*)sectorBuf[23]) + ((SHORTFILENAME_LEN+1) * subdirDepth); - strncpy(pSubdirName, selectedFile, SHORTFILENAME_LEN+1); - subdirDepth++; - - sd.chdir(selectedFile, true); - - diskMenuSelection = 0; - LcdClear(); - InitDiskMenu(sd); - DrawDiskMenu(sd); - _delay_ms(400); - } - else if (selectedFileType == DISK_IMAGE_UP_DIRECTORY) - { - subdirDepth--; - sd.chdir(true); // go to root directory - - for (uint8_t i=0; i -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "portmacros.h" -#include "noklcd.h" -//#include "millitimer.h" -#include "SdFat.h" -#include "SdBaseFile.h" -#include "micro.h" -#include "ports.h" -#include "diskmenu.h" - -#include "floppyemu.h" - -#ifdef PROGMEM_WORKAROUND -// work-around for compiler bug -#undef PROGMEM -#define PROGMEM __attribute__(( section(".progmem.data") )) -#undef PSTR -#define PSTR(s) (__extension__({static prog_char __c[] PROGMEM = (s); &__c[0];})) -#endif - -#ifndef FLOPPYEMU_H_ - -// I/O pin assignments -#define CPLD_RESET_PORT B -#define CPLD_RESET_PIN 0 - -#define CPLD_STEP_DIR_MOTOR_ON_PORT C -#define CPLD_STEP_DIR_MOTOR_ON_PIN 7 - -#define CPLD_STEP_REQ_PORT D -#define CPLD_STEP_REQ_PIN 0 // PCINT24 -#define CPLD_STEP_REQ_INT_MSK PCMSK3 -#define CPLD_STEP_REQ_INT_PIN PCINT24 -#define CPLD_STEP_REQ_INT_ENABLE PCIE3 - -#define CPLD_CURRENT_SIDE_PORT C -#define CPLD_CURRENT_SIDE_PIN 1 // PCINT17 -#define CPLD_CURRENT_SIDE_INT_MSK PCMSK2 -#define CPLD_CURRENT_SIDE_INT_PIN PCINT17 -#define CPLD_CURRENT_SIDE_INT_ENABLE PCIE2 - -#define CPLD_EJECT_REQ_PORT D -#define CPLD_EJECT_REQ_PIN 3 - -#define CPLD_STEP_ACK_DISK_IN_PORT C -#define CPLD_STEP_ACK_DISK_IN_PIN 2 - -#define CPLD_WR_REQ_PORT C -#define CPLD_WR_REQ_PIN 0 // PCINT16 -#define CPLD_WR_REQ_INT_MSK PCMSK2 -#define CPLD_WR_REQ_INT_PIN PCINT16 -#define CPLD_WR_REQ_INT_ENABLE PCIE2 - -#define CPLD_RD_READY_TK0_PORT C -#define CPLD_RD_READY_TK0_PIN 5 - -#define CPLD_RD_ACK_WR_TICK_PORT A -#define CPLD_RD_ACK_WR_TICK_PIN 7 // PCINT7 -#define CPLD_RD_ACK_WR_TICK_INT_MSK PCMSK0 -#define CPLD_RD_ACK_WR_TICK_INT_PIN PCINT7 -#define CPLD_RD_ACK_WR_TICK_INT_ENABLE PCIE0 - -#define CPLD_DATA_PORT A - -#define CPLD_DATA_HIZ_PORT C -#define CPLD_DATA_HIZ_PIN 6 - -#define CPLD_TACH_PORT D -#define CPLD_TACH_PIN 5 - -#define CPLD_TMS_PORT C -#define CPLD_TMS_PIN 3 - -#define SELECT_BUTTON_PORT D -#define SELECT_BUTTON_PIN 4 - -#define PREV_BUTTON_PORT D -#define PREV_BUTTON_PIN 1 - -#define NEXT_BUTTON_PORT D -#define NEXT_BUTTON_PIN 2 - -#define STATUS_LED_PORT B -#define STATUS_LED_PIN 3 - -#define CARD_WPROT_PORT D -#define CARD_WPROT_PIN 7 - -#endif - -#define SECTOR_DATA_SIZE 512 -#define INTER_SECTOR_GAP_SIZE 55 -#define ADDRESS_DATA_GAP_SIZE 10 -#define SECTOR_DATA_HEADER_SIZE 3 -#define SECTOR_DATA_SECTORNUM_START SECTOR_DATA_HEADER_SIZE -#define SECTOR_DATA_SECTORNUM_SIZE 1 -#define SECTOR_DATA_ENCODED_TAGS_START (SECTOR_DATA_HEADER_SIZE+SECTOR_DATA_SECTORNUM_SIZE) -#define SECTOR_DATA_ENCODED_TAGS_SIZE 16 -#define SECTOR_DATA_ENCODED_DATA_START (SECTOR_DATA_HEADER_SIZE+SECTOR_DATA_SECTORNUM_SIZE+SECTOR_DATA_ENCODED_TAGS_SIZE) -#define SECTOR_DATA_ENCODED_DATA_SIZE 683 -#define SECTOR_DATA_CHECKSUM_START (SECTOR_DATA_ENCODED_DATA_START+SECTOR_DATA_ENCODED_DATA_SIZE) - -// 8 byte marker placed at the end of the program binary, used by the bootloader. -// Configure the .bootldrinfo address to be 8 bytes below the bootloader start address for the type of Atmega being used. -#define DEVICEID_HIGH 0xDDDD -#define DEVICEID_LOW 0xDDDD -#define VERSIONID 0x0100 -const uint16_t bootloader_info[] __attribute__(( section(".bootldrinfo") )) = { DEVICEID_HIGH, DEVICEID_LOW, VERSIONID, 0x0000 }; - -const char versionStr[] PROGMEM = "App Version 1.0 L"; - -#ifndef FLOPPYEMU_H_ - -volatile uint8_t currentTrack; -volatile uint8_t prevTrack; -volatile uint8_t currentSide; -volatile uint8_t prevSide; -volatile uint8_t writeMode; -volatile bool restartDisk; -volatile bool writeError; - -bool diskInserted; -bool readOnly; -bool mfmMode; -uint16_t crc; -uint8_t numberOfDiskSides; -uint8_t currentSector; -uint16_t driveTachHalfPeriod; -uint8_t tachFlutter; - -uint8_t writeDisplayTimer; -uint8_t cpldFirmwareVersion; - -#define TEXTBUF_SIZE 22 -char textBuf[TEXTBUF_SIZE]; -#endif - -#define NUM_BUFFERS 24 -uint8_t sectorBuf[NUM_BUFFERS][SECTOR_DATA_SIZE]; -uint8_t extraBuf[SECTOR_DATA_SIZE]; - -bool selectedFileIsDiskCopyFormat; - -extern const uint16_t sony_track_start[] PROGMEM; -const uint16_t sony_track_start[80] = { - 0, 12, 24, 36, 48, 60 , 72, 84, - 96, 108, 120, 132, 144, 156, 168, 180, - - 192, 203, 214, 225, 236, 247, 258, 269, - 280, 291, 302, 313, 324, 335, 346, 357, - - 368, 378, 388, 398, 408, 418, 428, 438, - 448, 458, 468, 478, 488, 498, 508, 518, - - 528, 537, 546, 555, 564, 573, 582, 591, - 600, 609, 618, 627, 636, 645, 654, 663, - - 672, 680, 688, 696, 704, 712, 720, 728, - 736, 744, 752, 760, 768, 776, 784, 792 -}; - -extern const uint8_t sony_track_len[] PROGMEM; -const uint8_t sony_track_len[80] = { - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 -}; - -extern const uint8_t sony_to_disk_byte[] PROGMEM; -const uint8_t sony_to_disk_byte[] = { - 0x96, 0x97, 0x9A, 0x9B, 0x9D, 0x9E, 0x9F, 0xA6, /* 0x00 */ - 0xA7, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB2, 0xB3, - 0xB4, 0xB5, 0xB6, 0xB7, 0xB9, 0xBA, 0xBB, 0xBC, /* 0x10 */ - 0xBD, 0xBE, 0xBF, 0xCB, 0xCD, 0xCE, 0xCF, 0xD3, - 0xD6, 0xD7, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, /* 0x20 */ - 0xDF, 0xE5, 0xE6, 0xE7, 0xE9, 0xEA, 0xEB, 0xEC, - 0xED, 0xEE, 0xEF, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, /* 0x30 */ - 0xF7, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF -}; - -extern const uint8_t disk_byte_to_sony[] PROGMEM; -const uint8_t disk_byte_to_sony[] = { - /* table begins at disk byte 0x96, value of 0xFF is an invalid disk byte */ - /* 0x96 */ 0x00, 0x01, 0xFF, 0xFF, 0x02, 0x03, 0xFF, 0x04, - /* 0x9E */ 0x05, 0x06, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - /* 0xA6 */ 0x07, 0x08, 0xFF, 0xFF, 0xFF, 0x09, 0x0A, 0x0B, - /* 0xAE */ 0x0C, 0x0D, 0xFF, 0xFF, 0x0E, 0x0F, 0x10, 0x11, - /* 0xB6 */ 0x12, 0x13, 0xFF, 0x14, 0x15, 0x16, 0x17, 0x18, - /* 0xBE */ 0x19, 0x1A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - /* 0xC6 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1B, 0xFF, 0x1C, - /* 0xCE */ 0x1D, 0x1E, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, - /* 0xD6 */ 0x20, 0x21, 0xFF, 0x22, 0x23, 0x24, 0x25, 0x26, - /* 0xDE */ 0x27, 0x28, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x29, - /* 0xE6 */ 0x2A, 0x2B, 0xFF, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, - /* 0xEE */ 0x31, 0x32, 0xFF, 0xFF, 0x33, 0x34, 0x35, 0x36, - /* 0xF6 */ 0x37, 0x38, 0xFF, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, - /* 0xFE */ 0x3E, 0x3F -}; - -uint8_t sectorDataHeaderGCR[] = { 0xD5, 0xAA, 0xAD }; - -extern const uint16_t crc_ccitt[] PROGMEM; -const uint16_t crc_ccitt[] = { - 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, - 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, - 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, - 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, - 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, - 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, - 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, - 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, - 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, - 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, - 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, - 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, - 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, - 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, - 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, - 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, - 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, - 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, - 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, - 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, - 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, - 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, - 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, - 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, - 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, - 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, - 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, - 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, - 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, - 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, - 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, - 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0 -}; - -#ifndef FLOPPYEMU_H_ -void ResetDiskState(); -#endif - -uint16_t writeErrorNumber; - -void error(const char* msg) -{ - bool wasWriteError = writeError; - uint16_t wasWriteErrorNumber = writeErrorNumber; - - ResetDiskState(); // clears writeError and writeErrorNumber - - LcdClear(); - LcdGoto(0,0); - if (wasWriteError) - LcdTinyStringP(PSTR("WRITE ERROR "), TEXT_INVERSE); - else - LcdTinyStringP(PSTR("FATAL ERROR "), TEXT_INVERSE); - LcdGoto(0,1); - LcdTinyString(msg, TEXT_NORMAL); - - if (wasWriteError) - { - snprintf(textBuf, TEXTBUF_SIZE, "%u", wasWriteErrorNumber); - LcdGoto(0,5); - LcdTinyString(textBuf, TEXT_NORMAL); - } - - while (1); -} - -void InitPorts() -{ - // set all data lines as outputs, MSB (RD_ACK/WR_TICK) as input - DDR(CPLD_DATA_PORT) = 0x7F; - - // initialize the other output lines - DDR(CPLD_TACH_PORT) |= (1<> 4; - if (speedZone > 4) - speedZone = 4; - - ATOMIC_BLOCK(ATOMIC_RESTORESTATE) - { - driveTachHalfPeriod = F_CPU / (2 * zoneRPM[speedZone]); - // OCR1A update will be performed during the next sector 0 read - } - - TIFR1 = (1 << OCF1A); // Clear the timer 1 compare A match flag. Not sure this is actually necessary. -} - -uint16_t trackStart(uint8_t trackNumber) -{ - return mfmMode ? trackNumber * 18 : pgm_read_word(&sony_track_start[trackNumber]); -} - -uint8_t trackLength(uint8_t trackNumber) -{ - return mfmMode ? 18 : pgm_read_byte(&sony_track_len[trackNumber]); -} - -#define BUFFER_DIRTY 1 -#define BUFFER_DATA_VALID 2 -#define BUFFER_LOCKED 4 - -volatile uint8_t bufferState[NUM_BUFFERS]; -volatile uint8_t wrTrack; -volatile uint8_t wrSide; -volatile uint8_t wrSector; - -// these variables are used only within the interrupt routine, and do not need to be declared volatile -uint8_t wrTick; -uint16_t writeCount; -uint8_t writeTemp; -uint8_t currentWriteBufferNumber; -uint8_t ck5, ck6, ck7; -uint8_t XBit; -uint8_t* pSectorBuf; - -void WriteError() -{ - writeMode = false; - restartDisk = true; - writeError = true; - writeCount = 0; -} - -// pin state change interrupt: STEP -ISR(PCINT3_vect) -{ - // step to a new track? - if (bit_is_set(PIN(CPLD_STEP_REQ_PORT), CPLD_STEP_REQ_PIN)) - { - // determine the range of dirty sector buffers - uint8_t trackLen = trackLength(currentTrack); - uint8_t firstDirtyBuffer = NUM_BUFFERS, lastDirtyBuffer=0; - - for (uint8_t i=0; i= SECTOR_DATA_SECTORNUM_START) - { - strncpy(textBuf, "incomplete write", TEXTBUF_SIZE); - writeErrorNumber = 1000 + writeCount; - WriteError(); - } - - restartDisk = true; - } -} - -// pin state change interrupt: SIDE, WR_REQ -ISR(PCINT2_vect) -{ - // did the current side change? - uint8_t newSide = ((PIN(CPLD_CURRENT_SIDE_PORT) >> CPLD_CURRENT_SIDE_PIN) & 0x01); - if (newSide != currentSide) - { - if (numberOfDiskSides == 2) - currentSide = newSide; - else - currentSide = 0; - restartDisk = true; - - // premature end of a write? - if (writeCount >= SECTOR_DATA_SECTORNUM_START) - { - strncpy(textBuf, "incomplete write", TEXTBUF_SIZE); - writeErrorNumber = 2000 + writeCount; - WriteError(); - } - } - - // did the read/write mode change? RD_RW: 0 = write, 1 = read - uint8_t wreqBit = bit_is_clear(PIN(CPLD_WR_REQ_PORT), CPLD_WR_REQ_PIN); - if (wreqBit != writeMode) - { - writeMode = wreqBit; - - if (writeMode) - { - // switch the DATA pins to inputs - DDR(CPLD_DATA_PORT) = 0; - - // indicate that the data bus has been released - PORT(CPLD_DATA_HIZ_PORT) |= (1<= SECTOR_DATA_SECTORNUM_START) - { - strncpy(textBuf, "incomplete write", TEXTBUF_SIZE); - writeErrorNumber = 3000 + writeCount; - WriteError(); - } - } - - restartDisk = true; - } -} - -void HandleGCRWrite() -{ - uint8_t diskByte = 0x80 | PIN(CPLD_DATA_PORT); - - if (writeCount < SECTOR_DATA_ENCODED_TAGS_START) - { - // look for the sector header - // the final header byte is the sector number - if (writeCount == SECTOR_DATA_SECTORNUM_START) - { - uint8_t sector = pgm_read_byte(&disk_byte_to_sony[diskByte - 0x96]); - - if (sector >= trackLength(currentTrack)) - { - snprintf(textBuf, TEXTBUF_SIZE, "bad sector %d for t%d", sector, currentTrack); - writeErrorNumber = 60; - WriteError(); - } - - uint8_t trackLen = trackLength(currentTrack); - currentWriteBufferNumber = trackLen * currentSide + sector; - - if (bufferState[currentWriteBufferNumber] & BUFFER_LOCKED) - { - snprintf(textBuf, TEXTBUF_SIZE, "buf locked %d/%d:%d", currentTrack, currentSide, sector); - writeErrorNumber = 61; - WriteError(); - } - - pSectorBuf = sectorBuf[currentWriteBufferNumber]; - bufferState[currentWriteBufferNumber] |= BUFFER_LOCKED; - bufferState[currentWriteBufferNumber] &= ~BUFFER_DATA_VALID; - wrTrack = currentTrack; - wrSide = currentSide; - wrSector = sector; - - // turn on the LED when receiving a sector write - PORT(STATUS_LED_PORT) &= ~(1<> 7; - ck7 = (ck7 << 1) | XBit; - break; - - case 1: - b = (writeTemp & 0xC0) | dataIn; // A7 A6 0 0 0 0 0 0 | 0 0 A5 A4 A3 A2 A1 A0 - b ^= ck7; - - if (writeCount >= SECTOR_DATA_ENCODED_DATA_START) - *pSectorBuf++ = b; - - //ADDX(ck5, b); - addResult = (uint16_t)ck5 + b + XBit; - ck5 = addResult & 0xFF; - XBit = addResult >> 8; - writeTemp <<= 2; // B7 B6 C7 C6 0 0 0 0 - break; - - case 2: - b = (writeTemp & 0xC0) | dataIn; // B7 B6 0 0 0 0 0 0 | 0 0 B5 B4 B3 B2 B1 B0 - b ^= ck5; - - if (writeCount >= SECTOR_DATA_ENCODED_DATA_START) - *pSectorBuf++ = b; - - //ADDX(ck6, b); - addResult = (uint16_t)ck6 + b + XBit; - ck6 = addResult & 0xFF; - XBit = addResult >> 8; - writeTemp <<= 2; // C7 C6 0 0 0 0 0 0 - break; - - case 3: - b = writeTemp | dataIn; // C7 C6 0 0 0 0 0 0 | 0 0 C5 C4 C3 C2 C1 C0 - b ^= ck6; - - if (writeCount >= SECTOR_DATA_ENCODED_DATA_START) - *pSectorBuf++ = b; - - //ADDX(ck7, b); - addResult = (uint16_t)ck7 + b + XBit; - ck7 = addResult & 0xFF; - XBit = addResult >> 8; - break; - } - } - else - { - // verify the checksum - if (writeCount == SECTOR_DATA_CHECKSUM_START) - { - writeTemp = dataIn; - writeTemp <<= 2; - } - else if (writeCount == SECTOR_DATA_CHECKSUM_START+1) - { - b = (writeTemp & 0xC0) | dataIn; - writeTemp <<= 2; - if (b != ck5) - { - strncpy(textBuf, "checksum failure 0", TEXTBUF_SIZE); - writeErrorNumber = 62; - WriteError(); - } - } - else if (writeCount == SECTOR_DATA_CHECKSUM_START+2) - { - b = (writeTemp & 0xC0) | dataIn; - writeTemp <<= 2; - if (b != ck6) - { - strncpy(textBuf, "checksum failure 1", TEXTBUF_SIZE); - writeErrorNumber = 63; - WriteError(); - } - } - else if (writeCount == SECTOR_DATA_CHECKSUM_START+3) - { - b = writeTemp | dataIn; - writeTemp <<= 2; - if (b != ck7) - { - strncpy(textBuf, "checksum failure 2", TEXTBUF_SIZE); - writeErrorNumber = 64; - WriteError(); - } - - // success! - bufferState[currentWriteBufferNumber] |= BUFFER_DATA_VALID; - bufferState[currentWriteBufferNumber] |= BUFFER_DIRTY; - bufferState[currentWriteBufferNumber] &= ~BUFFER_LOCKED; - - // turn off the LED at the end of a sector write - PORT(STATUS_LED_PORT) |= (1<> 8) ^ 0xA1]); - crc = (crc << 8) ^ pgm_read_word(&crc_ccitt[(uint8_t)(crc >> 8) ^ 0xA1]); - crc = (crc << 8) ^ pgm_read_word(&crc_ccitt[(uint8_t)(crc >> 8) ^ 0xA1]); - crc = (crc << 8) ^ pgm_read_word(&crc_ccitt[(uint8_t)(crc >> 8) ^ 0xFB]); - - for (uint16_t i=0; i> 8) ^ sectorBuf[bufferNumber][i]]); - } - - if (crc != receivedCRC) - { - strncpy(textBuf, "checksum fail", TEXTBUF_SIZE); - writeErrorNumber = 70; - WriteError(); - } -} - -// pin state change interrupt: WR_TICK -ISR(PCINT0_vect) -{ - uint8_t wrTickBit = bit_is_set(PIN(CPLD_RD_ACK_WR_TICK_PORT), CPLD_RD_ACK_WR_TICK_PIN); - - // was a new byte written? - if (writeMode && wrTickBit != wrTick) - { - wrTick = wrTickBit; - - if (!mfmMode) - { - HandleGCRWrite(); - } - else - { - if (wrTickBit == 0) - { - // high nibble arrives first - writeTemp = (PIN(CPLD_DATA_PORT) << 4) & 0xF0; - return; - } - else - { - writeTemp |= (PIN(CPLD_DATA_PORT) & 0x0F); - - if (writeCount == 2) - { - if (writeTemp == 0xFB) - { - writeCount++; - - // header received OK! - currentWriteBufferNumber = currentSector; // assume the buffer to write was the last one read - - if (bufferState[currentWriteBufferNumber] & BUFFER_LOCKED) - { - snprintf(textBuf, TEXTBUF_SIZE, "buf locked %d/%d:%d", currentTrack, currentSide, currentSector); - writeErrorNumber = 71; - WriteError(); - return; - } - - pSectorBuf = sectorBuf[currentWriteBufferNumber]; - bufferState[currentWriteBufferNumber] |= BUFFER_LOCKED; - bufferState[currentWriteBufferNumber] &= ~BUFFER_DATA_VALID; - wrTrack = currentTrack; - wrSide = currentSide; - wrSector = currentSector; // assume the buffer to write was the last one read - - // turn on the LED when receiving a sector write - PORT(STATUS_LED_PORT) &= ~(1<> 2) | ((__c1 & 0xC0) >> 4) | ((__c2 & 0xC0) >> 6)) - -// rotate left -#define rot_ck0(__ck0) \ - do { \ - __ck0 &= 0xFF; \ - __ck0 = (__ck0 << 1) | (__ck0 >> 7);\ - } while(0) - -// ADC __ckr, __in; __out = __in ^ __ckl -#define enc_byte(__in, __out, __ckl, __ckr) \ - do { \ - uint8_t __d = __in; \ - __ckr += __d; \ - __ckr += (__ckl & 0x100) >> 8; \ - __ckl &= 0xFF; \ - __out = __d ^ __ckl; \ - } while(0) - -#define SendByteAndCheckRestart(b) \ - do { \ - if (restartDisk) \ - goto restart; \ - SendByte(b); \ - } while(0) - -void SendMFMSync() -{ - // send A1 sync - - // SendByte - // TODO: what if an interrupt has switched the data port to an input? This will turn on pull-ups - PORT(CPLD_DATA_PORT) = 0x0A; // data in bits 3-0, sync flag in bit 4 - PORT(CPLD_RD_READY_TK0_PORT) |= (1<> 8) ^ 0xA1]); - - // SendByte - // TODO: what if an interrupt has switched the data port to an input? This will turn on pull-ups - PORT(CPLD_DATA_PORT) = 0x11; // data in bits 3-0, sync flag in bit 4 - PORT(CPLD_RD_READY_TK0_PORT) |= (1<> 4) & 0x0F; - - //if (restartDisk) - // return; - - // SendByte - // TODO: what if an interrupt has switched the data port to an input? This will turn on pull-ups - PORT(CPLD_DATA_PORT) = out; - PORT(CPLD_RD_READY_TK0_PORT) |= (1<> 8) ^ data]); - - //if (restartDisk) - // return; - - // SendByte - // TODO: what if an interrupt has switched the data port to an input? This will turn on pull-ups - PORT(CPLD_DATA_PORT) = out; - PORT(CPLD_RD_READY_TK0_PORT) |= (1< 128) - lcd_vop--; - } - else if (bit_is_clear(PIN(SELECT_BUTTON_PORT), SELECT_BUTTON_PIN)) - { - eeprom_update_byte((uint8_t*)1, lcd_vop); - break; - } - - LcdWrite(LCD_CMD, 0x21); // LCD Extended Commands. - LcdWrite(LCD_CMD, lcd_vop); // Set LCD Vop (Contrast). - LcdWrite(LCD_CMD, 0x20); - } -} - -void PromptForFirmwareUpdate() -{ - LcdGoto(0,0); - LcdClear(); - LcdGoto(0,0); - LcdTinyStringP(PSTR("CPLD FIRMWARE UPDATE"), TEXT_NORMAL); - LcdGoto(0,2); - LcdTinyStringP(PSTR("Release buttons to"), TEXT_NORMAL); - LcdGoto(0,3); - LcdTinyStringP(PSTR("begin"), TEXT_NORMAL); - - // wait for the buttons to be released - while (bit_is_clear(PIN(PREV_BUTTON_PORT), PREV_BUTTON_PIN) || - bit_is_clear(PIN(NEXT_BUTTON_PORT), NEXT_BUTTON_PIN) || - bit_is_clear(PIN(SELECT_BUTTON_PORT), SELECT_BUTTON_PIN)) - {} - - LcdGoto(0,2); - LcdTinyStringP(PSTR("NEXT: Load firmware"), TEXT_NORMAL); - LcdGoto(0,3); - LcdTinyStringP(PSTR("PREV: Cancel"), TEXT_NORMAL); - _delay_ms(400); - - // wait for a button press - while (bit_is_set(PIN(PREV_BUTTON_PORT), PREV_BUTTON_PIN) && - bit_is_set(PIN(NEXT_BUTTON_PORT), NEXT_BUTTON_PIN) && - bit_is_set(PIN(SELECT_BUTTON_PORT),SELECT_BUTTON_PIN)) - {} - - if (bit_is_clear(PIN(NEXT_BUTTON_PORT), NEXT_BUTTON_PIN)) - { - UpdateFirmware(); - } - else - { - LcdClear(); - } -} - -uint32_t imageFirstBlock, imageLastBlock; - -bool OpenImageFile() -{ - LcdClear(); - LcdGoto(0,0); - LcdTinyString(selectedLongFile, TEXT_NORMAL); - - LcdGoto(0,1); - - // open the disk image file - // to-do: check if the file is read-only on the card - bool openOK = true; - if (!f.open(selectedFile, O_RDWR)) - { - if (f.open(selectedFile, O_RDONLY)) - { - // TODO: How do we tell the CPLD the disk is read-only? - readOnly = true; - } - else - { - LcdTinyStringP(PSTR("error opening image"), TEXT_NORMAL); - openOK = false; - } - } - else - { - if (selectedFileType == DISK_IMAGE_400K || selectedFileType == DISK_IMAGE_DISKCOPY_400K) - { - numberOfDiskSides = 1; - } - else - { - numberOfDiskSides = 2; - } - } - - // get address of file on SD - if (openOK && !f.contiguousRange(&imageFirstBlock, &imageLastBlock)) - { - LcdTinyStringP(PSTR("image not contiguous"), TEXT_NORMAL); - openOK = false; - } - - if (!openOK) - { - _delay_ms(4000); // wait 4 seconds - } - else - { - LcdGoto(0,1); - // show disk image type - switch (selectedFileType) - { - case DISK_IMAGE_400K: - LcdTinyStringP(PSTR("400K raw image"), TEXT_NORMAL); - break; - - case DISK_IMAGE_800K: - LcdTinyStringP(PSTR("800K raw image"), TEXT_NORMAL); - break; - - case DISK_IMAGE_1440K: - LcdTinyStringP(PSTR("1440K raw image"), TEXT_NORMAL); - mfmMode = true; - break; - - case DISK_IMAGE_DISKCOPY_400K: - LcdTinyStringP(PSTR("400K DiskCopy image"), TEXT_NORMAL); - break; - - case DISK_IMAGE_DISKCOPY_800K: - LcdTinyStringP(PSTR("800K DiskCopy image"), TEXT_NORMAL); - break; - - case DISK_IMAGE_DISKCOPY_1440K: - LcdTinyStringP(PSTR("1440K DiskCopy image"), TEXT_NORMAL); - mfmMode = true; - break; - - default: - break; - } - - selectedFileIsDiskCopyFormat = (selectedFileType >= DISK_IMAGE_DISKCOPY_400K); - - if (bit_is_set(PIN(CARD_WPROT_PORT), CARD_WPROT_PIN)) - readOnly = true; - - // mount DiskCopy images read-only - if (selectedFileIsDiskCopyFormat) - readOnly = true; - - uint16_t volumeNameOffset = selectedFileIsDiskCopyFormat ? 0x424 + 0x54 : 0x424; - f.seekSet(volumeNameOffset); // offset of the Macintosh disk name in the image file - f.read(§orBuf[0][0], SECTOR_DATA_SIZE); - int nameLen = sectorBuf[0][0]; - uint8_t* name = §orBuf[0][1]; - name[nameLen] = 0; - name[21] = 0; // in case nameLen was bogus, terminate the string after 21 chars, which is the longest displayable name on the LCD - LcdGoto(0,2); - LcdTinyString((char*)name, TEXT_NORMAL); - LcdGoto(0,4); - LcdTinyStringP(PSTR("Track Side"), TEXT_NORMAL); - - // show a lock icon if the disk image is mounted as read-only - if (readOnly) - { - LcdGoto(77,0); - LcdWrite(LCD_DATA, 0x00); - LcdWrite(LCD_DATA, 0x78); - LcdWrite(LCD_DATA, 0x7E); - LcdWrite(LCD_DATA, 0x79); - LcdWrite(LCD_DATA, 0x79); - LcdWrite(LCD_DATA, 0x7E); - LcdWrite(LCD_DATA, 0x78); - } - } - - f.close(); - return openOK; -} - -void ResetDiskState() -{ - ATOMIC_BLOCK(ATOMIC_RESTORESTATE) - { - // useless code to prevent the "unused" bootloader_info array from being optimized away when optimizations are turned on - // there's probably a nicer way to accomplish this. - currentTrack = bootloader_info[currentTrack]; - - InitPorts(); - - currentTrack = 0; - prevTrack = 0; - restartDisk = false; - currentSide = 0; - prevSide = 0; - writeMode = 0; - diskInserted = false; - numberOfDiskSides = 2; - currentSector = 0; - readOnly = false; - mfmMode = false; - writeError = false; - writeDisplayTimer = 0; - tachFlutter = 0; - writeErrorNumber = 0; - writeCount = 0; - - for (uint8_t i=0; i= trackLen - 1) - return 0; - else - return prevSectorNumber + 1; - } - else - { - uint8_t halfTrackLen = (trackLen + 1) >> 1; - - // process sectors in interleaved order: - // 12 sector tracks: 0 6 1 7 2 8 3 9 4 10 5 11 - // 11 sector tracks: 0 6 1 7 2 8 3 9 4 10 5 - // 10 sector tracks: 0 5 1 6 2 7 3 8 4 9 - // 9 sector tracks: 0 5 1 6 2 7 3 8 4 - // 8 sector tracks: 0 4 1 5 2 6 3 7 - // This is how real floppies are formatted, and should improve read performance if the Mac - // can't completely process sector N before sector N+1 begins. It should also improve sector-by-sector - // write performance, because the Mac alternately reads (address header) and writes (data section) in - // this mode, and proper interleaving means it will read the desired address header sooner if the Mac - // isn't fast enough to process the sectors linearly (which it likely isn't). - if (prevSectorNumber > trackLen - 1 || - ((trackLen & 1) == 0 && prevSectorNumber == trackLen - 1) || - ((trackLen & 1) == 1 && prevSectorNumber == halfTrackLen - 1)) - return 0; - else if (prevSectorNumber < halfTrackLen) - return prevSectorNumber + halfTrackLen; - else - return prevSectorNumber + 1 - halfTrackLen; - } -} - -void ReadDiskCopy42Block(SdFat& sd, uint32_t blockToRead, uint8_t bufferNumber) -{ - // for a DiskCopy 4.2 image, read two blocks into a temp buffer, then copy the unaligned data into the sector buffer. - uint16_t i; - - if (!sd.card()->readStart(blockToRead)) - error("SD read start error"); - - // read part 1 - if (!sd.card()->readData(extraBuf)) - error("SD read error D"); - for (i=0; i<512-0x54; i++) - sectorBuf[bufferNumber][i] = extraBuf[0x54 + i]; - - // read part 2 - if (!sd.card()->readData(extraBuf)) - error("SD read error D"); - for (i=512-0x54; i<512; i++) - sectorBuf[bufferNumber][i] = extraBuf[0x54 + i - 512]; - - sd.card()->readStop(); -} - -void FlushDirtySectors(SdFat& sd, uint8_t trackNumber) -{ - uint8_t trackLen = trackLength(trackNumber); - uint8_t firstDirtyBuffer = NUM_BUFFERS, lastDirtyBuffer=0; - - // determine the dirty range - for (uint8_t i=0; ireadBlock(blockToRead, sectorBuf[i])) - error("SD read error W"); - } - } - - uint32_t firstBlockToWrite = imageFirstBlock + ((uint32_t)trackStart(trackNumber) * numberOfDiskSides + firstDirtyBuffer); - - if (mfmMode) - firstBlockToWrite += trackLen * wrSide; - - uint32_t numBuffersToWrite = lastDirtyBuffer + 1 - firstDirtyBuffer; - - if (!sd.card()->writeStart(firstBlockToWrite, numBuffersToWrite)) - error("SD writeStart fail"); - - for (uint8_t i=firstDirtyBuffer; i<=lastDirtyBuffer; i++) - { - if (!sd.card()->writeData(sectorBuf[i])) - error("SD write error"); - - bufferState[i] &= ~BUFFER_DIRTY; - bufferState[i] &= ~BUFFER_LOCKED; - } - - if (!sd.card()->writeStop()) - error("SD writeStop fail"); - - writeDisplayTimer = 25; - millitimerOff(); - - uint32_t writeTime = millis() - t0; - - snprintf(textBuf, TEXTBUF_SIZE, "Saved trk %02d in %lu ", trackNumber, writeTime); - LcdGoto(0,5); - LcdTinyString(textBuf, TEXT_NORMAL); - } - } -} - - diff --git a/floppy_emu_arduino/floppyemu.h b/floppy_emu_arduino/floppyemu.h deleted file mode 100644 index bdcc75f..0000000 --- a/floppy_emu_arduino/floppyemu.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * floppyemu.h - * - * Created on: 2014/07/12 - * Author: sin - */ - -#ifndef FLOPPYEMU_H_ -#define FLOPPYEMU_H_ - -// I/O pin assignments -#define CPLD_RESET_PORT B -#define CPLD_RESET_PIN 0 - -#define CPLD_STEP_DIR_MOTOR_ON_PORT C -#define CPLD_STEP_DIR_MOTOR_ON_PIN 7 - -#define CPLD_STEP_REQ_PORT D -#define CPLD_STEP_REQ_PIN 0 // PCINT24 -#define CPLD_STEP_REQ_INT_MSK PCMSK3 -#define CPLD_STEP_REQ_INT_PIN PCINT24 -#define CPLD_STEP_REQ_INT_ENABLE PCIE3 - -#define CPLD_CURRENT_SIDE_PORT C -#define CPLD_CURRENT_SIDE_PIN 1 // PCINT17 -#define CPLD_CURRENT_SIDE_INT_MSK PCMSK2 -#define CPLD_CURRENT_SIDE_INT_PIN PCINT17 -#define CPLD_CURRENT_SIDE_INT_ENABLE PCIE2 - -#define CPLD_EJECT_REQ_PORT D -#define CPLD_EJECT_REQ_PIN 3 - -#define CPLD_STEP_ACK_DISK_IN_PORT C -#define CPLD_STEP_ACK_DISK_IN_PIN 2 - -#define CPLD_WR_REQ_PORT C -#define CPLD_WR_REQ_PIN 0 // PCINT16 -#define CPLD_WR_REQ_INT_MSK PCMSK2 -#define CPLD_WR_REQ_INT_PIN PCINT16 -#define CPLD_WR_REQ_INT_ENABLE PCIE2 - -#define CPLD_RD_READY_TK0_PORT C -#define CPLD_RD_READY_TK0_PIN 5 - -#define CPLD_RD_ACK_WR_TICK_PORT A -#define CPLD_RD_ACK_WR_TICK_PIN 7 // PCINT7 -#define CPLD_RD_ACK_WR_TICK_INT_MSK PCMSK0 -#define CPLD_RD_ACK_WR_TICK_INT_PIN PCINT7 -#define CPLD_RD_ACK_WR_TICK_INT_ENABLE PCIE0 - -#define CPLD_DATA_PORT A - -#define CPLD_DATA_HIZ_PORT C -#define CPLD_DATA_HIZ_PIN 6 - -#define CPLD_TACH_PORT D -#define CPLD_TACH_PIN 5 - -#define CPLD_TMS_PORT C -#define CPLD_TMS_PIN 3 - -#define SELECT_BUTTON_PORT D -#define SELECT_BUTTON_PIN 4 - -#define PREV_BUTTON_PORT D -#define PREV_BUTTON_PIN 1 - -#define NEXT_BUTTON_PORT D -#define NEXT_BUTTON_PIN 2 - -#define STATUS_LED_PORT B -#define STATUS_LED_PIN 3 - -#define CARD_WPROT_PORT D -#define CARD_WPROT_PIN 7 - -// global variables predefinitions - -#define TEXTBUF_SIZE 22 -char textBuf[TEXTBUF_SIZE]; - -volatile uint8_t currentTrack; -volatile uint8_t prevTrack; -volatile uint8_t currentSide; -volatile uint8_t prevSide; -volatile uint8_t writeMode; -volatile bool restartDisk; -volatile bool writeError; - -bool diskInserted; -bool readOnly; -bool mfmMode; -uint16_t crc; -uint8_t numberOfDiskSides; -uint8_t currentSector; -uint16_t driveTachHalfPeriod; -uint8_t tachFlutter; - -uint8_t writeDisplayTimer; -uint8_t cpldFirmwareVersion; - -// public functions predefinitions - -void ResetDiskState(); -void ShowVersion(); -void AdjustContrast(void); -void error(const char* msg); -void PromptForFirmwareUpdate(); - -#endif /* FLOPPYEMU_H_ */ diff --git a/floppy_emu_arduino/noklcd.cpp b/floppy_emu_arduino/noklcd.cpp index 1bb86e8..24c1523 100755 --- a/floppy_emu_arduino/noklcd.cpp +++ b/floppy_emu_arduino/noklcd.cpp @@ -306,7 +306,7 @@ void LcdClear(void) void LcdReset(void) { - lcd_vop = 0xBF; + lcd_vop = 0xa4; //0xBF; lcd_bias = 0x14; lcd_tempCoef = 0x04; diff --git a/floppy_emu_arduino/bootldr/bootldr.atsln b/floppy_emu_bootloader/bootldr.atsln similarity index 100% rename from floppy_emu_arduino/bootldr/bootldr.atsln rename to floppy_emu_bootloader/bootldr.atsln diff --git a/floppy_emu_arduino/bootldr/bootldr.atsuo b/floppy_emu_bootloader/bootldr.atsuo similarity index 100% rename from floppy_emu_arduino/bootldr/bootldr.atsuo rename to floppy_emu_bootloader/bootldr.atsuo diff --git a/floppy_emu_arduino/bootldr/bootldr/Release/Makefile b/floppy_emu_bootloader/bootldr/Release/Makefile similarity index 100% rename from floppy_emu_arduino/bootldr/bootldr/Release/Makefile rename to floppy_emu_bootloader/bootldr/Release/Makefile diff --git a/floppy_emu_arduino/bootldr/bootldr/Release/bootldr.hex b/floppy_emu_bootloader/bootldr/Release/bootldr.hex similarity index 100% rename from floppy_emu_arduino/bootldr/bootldr/Release/bootldr.hex rename to floppy_emu_bootloader/bootldr/Release/bootldr.hex diff --git a/floppy_emu_arduino/bootldr/bootldr/Release/makedep.mk b/floppy_emu_bootloader/bootldr/Release/makedep.mk similarity index 100% rename from floppy_emu_arduino/bootldr/bootldr/Release/makedep.mk rename to floppy_emu_bootloader/bootldr/Release/makedep.mk diff --git a/floppy_emu_arduino/bootldr/bootldr/asmfunc.S b/floppy_emu_bootloader/bootldr/asmfunc.S similarity index 100% rename from floppy_emu_arduino/bootldr/bootldr/asmfunc.S rename to floppy_emu_bootloader/bootldr/asmfunc.S diff --git a/floppy_emu_arduino/bootldr/bootldr/bootldr.c b/floppy_emu_bootloader/bootldr/bootldr.c similarity index 100% rename from floppy_emu_arduino/bootldr/bootldr/bootldr.c rename to floppy_emu_bootloader/bootldr/bootldr.c diff --git a/floppy_emu_arduino/bootldr/bootldr/bootldr.cproj b/floppy_emu_bootloader/bootldr/bootldr.cproj similarity index 100% rename from floppy_emu_arduino/bootldr/bootldr/bootldr.cproj rename to floppy_emu_bootloader/bootldr/bootldr.cproj diff --git a/floppy_emu_arduino/bootldr/bootldr/diskio.h b/floppy_emu_bootloader/bootldr/diskio.h similarity index 100% rename from floppy_emu_arduino/bootldr/bootldr/diskio.h rename to floppy_emu_bootloader/bootldr/diskio.h diff --git a/floppy_emu_arduino/bootldr/bootldr/integer.h b/floppy_emu_bootloader/bootldr/integer.h similarity index 100% rename from floppy_emu_arduino/bootldr/bootldr/integer.h rename to floppy_emu_bootloader/bootldr/integer.h diff --git a/floppy_emu_arduino/bootldr/bootldr/lcd.c b/floppy_emu_bootloader/bootldr/lcd.c similarity index 100% rename from floppy_emu_arduino/bootldr/bootldr/lcd.c rename to floppy_emu_bootloader/bootldr/lcd.c diff --git a/floppy_emu_arduino/bootldr/bootldr/lcd.h b/floppy_emu_bootloader/bootldr/lcd.h similarity index 100% rename from floppy_emu_arduino/bootldr/bootldr/lcd.h rename to floppy_emu_bootloader/bootldr/lcd.h diff --git a/floppy_emu_arduino/bootldr/bootldr/main.c b/floppy_emu_bootloader/bootldr/main.c similarity index 100% rename from floppy_emu_arduino/bootldr/bootldr/main.c rename to floppy_emu_bootloader/bootldr/main.c diff --git a/floppy_emu_arduino/bootldr/bootldr/mmc.c b/floppy_emu_bootloader/bootldr/mmc.c similarity index 100% rename from floppy_emu_arduino/bootldr/bootldr/mmc.c rename to floppy_emu_bootloader/bootldr/mmc.c diff --git a/floppy_emu_arduino/bootldr/bootldr/pff.c b/floppy_emu_bootloader/bootldr/pff.c similarity index 100% rename from floppy_emu_arduino/bootldr/bootldr/pff.c rename to floppy_emu_bootloader/bootldr/pff.c diff --git a/floppy_emu_arduino/bootldr/bootldr/pff.h b/floppy_emu_bootloader/bootldr/pff.h similarity index 100% rename from floppy_emu_arduino/bootldr/bootldr/pff.h rename to floppy_emu_bootloader/bootldr/pff.h diff --git a/floppy_emu_arduino/bootldr/how to configure bootloader.txt b/floppy_emu_bootloader/how to configure bootloader.txt similarity index 100% rename from floppy_emu_arduino/bootldr/how to configure bootloader.txt rename to floppy_emu_bootloader/how to configure bootloader.txt