├── .gitattributes ├── .gitignore ├── AppleIISd.sln ├── Binary ├── AppleCommander-ac-1.5.0.jar ├── AppleIISd.bin ├── AppleIISd.bom.txt ├── AppleIISd.hex ├── AppleIISd.pdf ├── AppleIISd_PC44.jed ├── AppleIISd_VQ44.jed ├── Flasher.bin ├── Flasher.dsk ├── Gerber_V1.1.zip ├── Gerber_V1.2.1.zip ├── Gerber_V1.2.zip └── ProFile.zip ├── Datasheets ├── 104H-TDA0-R.pdf ├── 65SPI-B Datasheet V1.1.docx ├── 65SPI-B Datasheet V1.1.pdf ├── 74LS245.pdf ├── AT28C64.pdf ├── AT28C64B.pdf ├── AppleII_Timing.json ├── AppleII_Timing.png ├── EEPROM_Timing.json ├── EEPROM_Timing.png ├── LM1117.pdf ├── M2716.pdf ├── M2732A.pdf ├── M48Z12.pdf ├── SD Specification - Part 1 Physical Layer Simplified.pdf ├── Timings.pptx ├── Xilinx DS054.pdf ├── Xilinx DS057.pdf ├── Xilinx XAPP112.pdf ├── at28c16.pdf └── plcc44_bottom.jpg ├── Firmware ├── AppleIISd.vcxproj ├── AppleIISd.vcxproj.filters ├── make_image.bat ├── make_image.sh ├── makefile └── src │ ├── AppleIISd.cfg │ ├── AppleIISd.inc │ ├── AppleIISd.s │ ├── Helper.s │ ├── ProDOS.s │ └── Smartport.s ├── Hardware ├── PCB-POOL Standard.dru ├── SD_A2.brd ├── SD_A2.gpi ├── SD_A2.sch ├── TagConnect.lbr ├── con-apple2.lbr ├── con-sd-attend2.lbr ├── lm1117.lbr ├── pda.lbr └── xilinx-xc9.lbr ├── Images ├── AddessDecoder_Test.JPG ├── AppleIISd_Test.JPG ├── Bus1.gif ├── Bus2.gif ├── Card Front SMD.jpg ├── Card Front.jpg ├── Spi1.png └── Spi2.png ├── README.md ├── Software ├── Flasher.vcxproj ├── Flasher.vcxproj.filters ├── apple2enh-system.cfg ├── make_image.bat ├── make_image.sh ├── makefile └── src │ ├── AppleIISd.h │ └── Flasher.c └── VHDL ├── AddressDecoder.vhd ├── AddressDecoder_Test.vhd ├── AppleIISd.vhd ├── AppleIISd_PC44.ucf ├── AppleIISd_PC44.xise ├── AppleIISd_Test.vhd ├── AppleIISd_VQ44.ucf ├── AppleIISd_VQ44.xise └── SpiController.vhd /.gitattributes: -------------------------------------------------------------------------------- 1 | Hardware/* linguist-vendored 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #ignore OS noise 2 | 3 | Thumbs.db 4 | .DS_Store 5 | 6 | #Ignore files build by Visual Studio 7 | *.obj 8 | *.exe 9 | *.pdb 10 | *.user 11 | *.aps 12 | *.pch 13 | *.vspscc 14 | *_i.c 15 | *_p.c 16 | *.ncb 17 | *.suo 18 | *.tlb 19 | *.tlh 20 | *.bak 21 | *.cache 22 | *.ilk 23 | *.log 24 | [Bb]in 25 | [Dd]ebug*/ 26 | *.lib 27 | *.sbr 28 | obj/ 29 | [Rr]elease*/ 30 | _ReSharper*/ 31 | [Tt]est[Rr]esult* 32 | .vs/ 33 | 34 | *.opendb 35 | **/Debug 36 | *.db 37 | *.dbg 38 | *.lbl 39 | *.map 40 | Makefile\.options 41 | 42 | # Ignore list for Eagle, a PCB layout tool 43 | 44 | # Backup files 45 | *.s#? 46 | *.b#? 47 | *.l#? 48 | 49 | # Eagle project file 50 | # It contains a serial number and references to the file structure 51 | # on your computer. 52 | # comment the following line if you want to have your project file included. 53 | eagle.epf 54 | 55 | # Autorouter files 56 | *.pro 57 | *.job 58 | 59 | # CAM files 60 | *.$$$ 61 | *.cmp 62 | *.ly2 63 | *.l15 64 | *.sol 65 | *.plc 66 | *.stc 67 | *.sts 68 | *.crc 69 | *.crs 70 | 71 | *.dri 72 | *.drl 73 | *.gpi 74 | *.pls 75 | 76 | *.drd 77 | *.drd.* 78 | 79 | *.info 80 | 81 | *.eps 82 | 83 | *.?$? 84 | 85 | # file locks introduced since 7.x 86 | *.lck 87 | 88 | # Xilinx ISE 89 | # intermediate build files 90 | *.bgn 91 | *.bit 92 | *.bld 93 | *.cmd_log 94 | *.drc 95 | *.ll 96 | *.lso 97 | *.msd 98 | *.msk 99 | *.ncd 100 | *.ngc 101 | *.ngd 102 | *.ngr 103 | *.pad 104 | *.par 105 | *.pcf 106 | *.prj 107 | *.ptwx 108 | *.rbb 109 | *.rbd 110 | *.stx 111 | *.syr 112 | *.twr 113 | *.twx 114 | *.unroutes 115 | *.ut 116 | *.xpi 117 | *.xst 118 | *_bitgen.xwbt 119 | *_envsettings.html 120 | *_map.map 121 | *_map.mrp 122 | *_map.ngm 123 | *_map.xrpt 124 | *_ngdbuild.xrpt 125 | *_pad.csv 126 | *_pad.txt 127 | *_par.xrpt 128 | *_summary.html 129 | *_summary.xml 130 | *_usage.xml 131 | *_xst.xrpt 132 | 133 | 134 | *.log 135 | *.svf 136 | *.scr 137 | *.cmd 138 | *.bak 139 | *.lso 140 | *.elf 141 | *.ace 142 | *~ 143 | *# 144 | *.swp 145 | *.ini 146 | *.html 147 | *.vhi 148 | *.wdb 149 | *.stx 150 | *.xmsgs 151 | *.xreport 152 | *.exe 153 | *.cmd_log 154 | *_beh.prj 155 | *.ncd 156 | isim 157 | db 158 | incremental_db 159 | work 160 | *.cr.mti 161 | vsim.wlf 162 | transcript 163 | webtalk.log 164 | webtalk_impact.xml 165 | pepExtractor.prj 166 | impact.xsl 167 | impact_impact.xwbt 168 | 169 | spi6502b_html*/ 170 | __projnav*/ 171 | 172 | # iMPACT generated files 173 | _impactbatch.log 174 | impact.xsl 175 | impact_impact.xwbt 176 | ise_impact.cmd 177 | webtalk_impact.xml 178 | 179 | # Core Generator generated files 180 | xaw2verilog.log 181 | 182 | # project-wide generated files 183 | *.gise 184 | par_usage_statistics.html 185 | usage_statistics_webtalk.html 186 | webtalk.log 187 | webtalk_pn.xml 188 | 189 | # generated folders 190 | iseconfig/ 191 | xlnx_auto_0_xdb/ 192 | xst/ 193 | _ngo/ 194 | _xmsgs/ 195 | VHDL/*_html 196 | VHDL/*.vhf 197 | VHDL/*.dhp 198 | VHDL/*.gyd 199 | VHDL/*.mfd 200 | VHDL/*.pnx 201 | VHDL/*.rpt 202 | VHDL/*.untf 203 | VHDL/*.vm6 204 | VHDL/*.xml 205 | VHDL/*.err 206 | VHDL/*.lfp 207 | 208 | Hardware/SD_A2\.b\$1 209 | 210 | 211 | *.vf 212 | 213 | *.nga 214 | 215 | *.tspec 216 | 217 | 218 | VHDL/_pace\.ucf 219 | 220 | VHDL/AppleIISd\.tim 221 | 222 | VHDL/AppleIISd\.jed 223 | 224 | Firmware/AppleIISd.bin 225 | 226 | Software/Flasher.bin 227 | -------------------------------------------------------------------------------- /AppleIISd.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AppleIISd", "Firmware\AppleIISd.vcxproj", "{9EA7EC3D-1771-420F-932F-231A35ED1200}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Flasher", "Software\Flasher.vcxproj", "{B2CF2E9D-62A7-4A68-9477-9B15A8707E78}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|x86 = Debug|x86 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {9EA7EC3D-1771-420F-932F-231A35ED1200}.Debug|x86.ActiveCfg = Debug|Win32 17 | {9EA7EC3D-1771-420F-932F-231A35ED1200}.Debug|x86.Build.0 = Debug|Win32 18 | {9EA7EC3D-1771-420F-932F-231A35ED1200}.Release|x86.ActiveCfg = Release|Win32 19 | {9EA7EC3D-1771-420F-932F-231A35ED1200}.Release|x86.Build.0 = Release|Win32 20 | {B2CF2E9D-62A7-4A68-9477-9B15A8707E78}.Debug|x86.ActiveCfg = Debug|Win32 21 | {B2CF2E9D-62A7-4A68-9477-9B15A8707E78}.Debug|x86.Build.0 = Debug|Win32 22 | {B2CF2E9D-62A7-4A68-9477-9B15A8707E78}.Release|x86.ActiveCfg = Release|Win32 23 | {B2CF2E9D-62A7-4A68-9477-9B15A8707E78}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /Binary/AppleCommander-ac-1.5.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freitz85/AppleIISd/b13ed9077f54387077b36edc959048bec4b9f689/Binary/AppleCommander-ac-1.5.0.jar -------------------------------------------------------------------------------- /Binary/AppleIISd.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freitz85/AppleIISd/b13ed9077f54387077b36edc959048bec4b9f689/Binary/AppleIISd.bin -------------------------------------------------------------------------------- /Binary/AppleIISd.bom.txt: -------------------------------------------------------------------------------- 1 | Qty Value Device Package Parts Description 2 | 1 LEDSQR2X5 LED2X5 LED1 LED 3 | 1 MA03-1 MA03-1 SV1 PIN HEADER 4 | 1 MA06-1 MA06-1 SV2 PIN HEADER 5 | 1 100k GE08R SIL9 RN1 SIL RESISTOR 6 | 8 100n C-EUC0603K C0603K C1, C2, C4, C5, C6, C7, C8, C9 CAPACITOR, European symbol 7 | 1 104H-TDA0-R 104H-TDA0-R 104H-TDA0-R U$2 SD Card Socket 8 | 3 10n C-EUC0603K C0603K C10, C11, C12 CAPACITOR, European symbol 9 | 2 10u/16V CPOL-EUA/3216-18R A/3216-18R C3, C13 POLARIZED CAPACITOR, European symbol 10 | 1 28C64ASO 28C64ASO SO28W IC3 CMOS EEPROM 11 | 1 470 R-EU_R0603 R0603 R4 RESISTOR, European symbol 12 | 1 74LS245N 74LS245N DIL20 IC1 Octal BUS TRANSCEIVER, 3-state 13 | 1 LM1117DTX-3.3 LM1117DTX-3.3 TO252 IC2 14 | 1 XC9572XL XC9572_S44VQFP SQFP-S-10X10-44 IC4 15 | -------------------------------------------------------------------------------- /Binary/AppleIISd.hex: -------------------------------------------------------------------------------- 1 | :10000000A220A200A203A20078A960853F203F00A1 2 | :10001000BABD0001588DF807290F853FA80A0A0AC2 3 | :100020000A853EAA2CFFCFA000B907C9F00D0980B0 4 | :10003000995007C810F3A9C520A8FC2C61C0100B6B 5 | :10004000ADF8073A854164406C40002000C8C90003 6 | :10005000D0EEA9088545644464476446206ECAB062 7 | :10006000DFA90A854564446447A9018546206ECA14 8 | :10007000B0CE4C01081890013808FAA004B93D0030 9 | :10008000488810F9863D78A960853F203F00BABDB9 10 | :100090000001588DF807290F853FA80A0A0A0A852A 11 | :1000A0003EAA2CFFCF202FCA9004A92F8015A9802B 12 | :1000B0003C83C0D0052000C8B009A53D4828B03415 13 | :1000C0002047CADAA63F9D7804689DF804989D7879 14 | :1000D0000508689DF805A00068993D00C8C0059016 15 | :1000E000F7BDF80548BD780548BDF80448BD78045B 16 | :1000F000FA7A2860182048CB80C900000000977564 17 | :100100009E81C0A9019D83C0A00AA9FF9D80C03C1B 18 | :1001100081C010FB88D0F5BD83C029FE9D83C0A996 19 | :100120002F8540A9C98541205FC92073C9C901D065 20 | :1001300065A93B8540A9C98541205FC9208AC9C9F5 21 | :1001400001D056A43FB9F805C9AAD04AA9478540AD 22 | :10015000A9C98541205FC92073C9A9538540A9C990 23 | :100160008541205FC92073C9C901F0E0C900D026CC 24 | :10017000A94D8540A9C98541205FC9208AC9C90008 25 | :10018000D014A43FB978042940F048BD83C00910B9 26 | :100190009D83C04CE5C84CFAC8A9478540A9C985CC 27 | :1001A00041205FC9A9598540A9C98541205FC9205F 28 | :1001B00073C9C901F0E3C900D0034CD3C8A9358580 29 | :1001C00040A9C98541205FC92073C9C901F0F6C99A 30 | :1001D00000D027A9418540A9C98541205FC9207366 31 | :1001E000C9C900D015BD83C009809D83C0BD81C031 32 | :1001F00009049D81C018A000900338A027BD83C0CA 33 | :1002000009019D83C09860204170706C655D5B53EF 34 | :10021000642076312E322E3220286329323032305B 35 | :1002200020466C6F7269616E20526569747A004075 36 | :1002300000000000954100000000F948000001AAFC 37 | :10024000875000000200FF7700000000FF7A0000E6 38 | :100250000000FF6940000000776900000000FF5ABD 39 | :10026000A000B1409D80C03C81C010FBC8C006907A 40 | :10027000F17A60A9FF9D80C03C81C010FBBD80C0A9 41 | :1002800030F148A9FF9D80C068602073C9485AA01A 42 | :10029000044C99C9A9FF9D80C03C81C010FBBD8062 43 | :1002A000C04888D0EFA43F6899F805689978056838 44 | :1002B00099F804689978047AA9FF9D80C06860DA8B 45 | :1002C0005AA63FA43EA5469DF805A5479D78059EE4 46 | :1002D000F8049E78049845432970F005A9029DF81A 47 | :1002E0000424431007BDF8041A9DF804A9103983AB 48 | :1002F000C0D011A0091EF8053E78053EF8043E78EE 49 | :100300000488D0F17AFA605AA43F9D80C0B978047D 50 | :100310009D80C0B9F8049D80C0B978059D80C0B9A2 51 | :10032000F8059D80C0A9FF9D80C02073C97A6048F0 52 | :10033000A9403C83C018F00138686048A9203C837C 53 | :10034000C018F001386860A542F00CC901F00BC973 54 | :1003500002F00AA90138604C60CA4C6ECA4CD7CA78 55 | :10036000A900203BCA9002A92BA2FFA0FF6020BFDA 56 | :10037000C9BD83C029FE9D83C0A9512007CAC900F9 57 | :10038000D050A9FF9D80C0BD80C0C9FED0F4BD8102 58 | :10039000C009109D81C0A9FF9D80C0A000BD80C084 59 | :1003A0009144C8D0F8E645BD80C09144C8D0F8C695 60 | :1003B00045BD80C0BD80C0BD80C0BD81C029EF9D4E 61 | :1003C00081C018A9000848BD83C009019D83C06889 62 | :1003D000286038A92780EE203BCAB06720BFC9BD7E 63 | :1003E00083C029FE9D83C0A9582007CAC900D04EEA 64 | :1003F000A9FF9D80C0A9FE9D80C0A000B1449D8042 65 | :10040000C0C8D0F8E645B1449D80C0C8D0F8C64504 66 | :10041000A9FF9D80C09D80C09D80C0BD80C0291F58 67 | :10042000C905D01A18A9000848A9FF9D80C0BD8041 68 | :10043000C0F0F6BD83C009019D83C068286038A95B 69 | :100440002780E438A92B80DFA004B9480048881031 70 | :10045000F9BABD0D0185481869039D0D01BD0E0156 71 | :10046000854969009D0E01A001B1488542C8B14887 72 | :10047000AAC8B14885498648A901A642E00AB01A2F 73 | :10048000B248DDDECCD027A001B148A43F99780660 74 | :100490008A0AAA20B2CBB002A900AAA00068994893 75 | :1004A00000C8C00590F78AA002A200C90160A90493 76 | :1004B00080E87CE8CC2043CCA43FB97806D018A5CE 77 | :1004C0004CF004A9213860A904924AA007B9FBCCDA 78 | :1004D000914A88D0F81860A64CF016CAF008CACA2B 79 | :1004E000F00FA9213860A901924AA8A900914A18E1 80 | :1004F00060A9E8A63E202FCAB0020910203BCA908E 81 | :10050000020904924AA001A9FF914AC8914AC8A9C8 82 | :1005100000914AA54CF00CA004B9FFCC914AC8C088 83 | :100520001990F618602043CCA64CF00FCAF00CCA04 84 | :10053000F006CAF00ACAF003A92138A9001860A978 85 | :100540001F3860A002B148854AC8B148854BC8B180 86 | :1005500048854C60206ECC900160A63EA43F4C6E56 87 | :10056000CA206ECC900160A63EA43F4CD7CAB97891 88 | :1005700006F044C901F00EC902F00EC903F010C91B 89 | :1005800004F0118032A53E8010A53E0980800AA5A6 90 | :100590003E3A8005A53E3A09808543A002B14885D0 91 | :1005A00044C8B1488545C8B1488546C8B148854763 92 | :1005B000C8B148D0061860A9113860A92D3860B9B3 93 | :1005C0007806F004A9001860A9113860B9780618F7 94 | :1005D000F003A9113860A9013860A9273860030326 95 | :1005E0000301030101010404B5CB54CC61CCBFCCA1 96 | :1005F00025CCCCCCD6CCD6CCDACCDACC4000000B97 97 | :10060000120000104150504C455D5B5344202020A7 98 | :100610002020202002000B1200000000000000003B 99 | :1006200000000000000000000000000000000000CA 100 | :1006300000000000000000000000000000000000BA 101 | :1006400000000000000000000000000000000000AA 102 | :10065000000000000000000000000000000000009A 103 | :10066000000000000000000000000000000000008A 104 | :10067000000000000000000000000000000000007A 105 | :10068000000000000000000000000000000000006A 106 | :10069000000000000000000000000000000000005A 107 | :1006A000000000000000000000000000000000004A 108 | :1006B000000000000000000000000000000000003A 109 | :1006C000000000000000000000000000000000002A 110 | :1006D000000000000000000000000000000000001A 111 | :1006E000000000000000000000000000000000000A 112 | :1006F00000000000000000000000000000000000FA 113 | :1007000000000000000000000000000000000000E9 114 | :1007100000000000000000000000000000000000D9 115 | :1007200000000000000000000000000000000000C9 116 | :1007300000000000000000000000000000000000B9 117 | :1007400000000000000000000000000000000000A9 118 | :100750000000000000000000000000000000000099 119 | :100760000000000000000000000000000000000089 120 | :100770000000000000000000000000000000000079 121 | :100780000000000000000000000000000000000069 122 | :100790000000000000000000000000000000000059 123 | :1007A0000000000000000000000000000000000049 124 | :1007B0000000000000000000000000000000000039 125 | :1007C0000000000000000000000000000000000029 126 | :1007D0000000000000000000000000000000000019 127 | :1007E0000000000000000000000000000000000009 128 | :1007F00000000000000000000000000000000000F9 129 | :00000001FF 130 | -------------------------------------------------------------------------------- /Binary/AppleIISd.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freitz85/AppleIISd/b13ed9077f54387077b36edc959048bec4b9f689/Binary/AppleIISd.pdf -------------------------------------------------------------------------------- /Binary/Flasher.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freitz85/AppleIISd/b13ed9077f54387077b36edc959048bec4b9f689/Binary/Flasher.bin -------------------------------------------------------------------------------- /Binary/Flasher.dsk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freitz85/AppleIISd/b13ed9077f54387077b36edc959048bec4b9f689/Binary/Flasher.dsk -------------------------------------------------------------------------------- /Binary/Gerber_V1.1.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freitz85/AppleIISd/b13ed9077f54387077b36edc959048bec4b9f689/Binary/Gerber_V1.1.zip -------------------------------------------------------------------------------- /Binary/Gerber_V1.2.1.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freitz85/AppleIISd/b13ed9077f54387077b36edc959048bec4b9f689/Binary/Gerber_V1.2.1.zip -------------------------------------------------------------------------------- /Binary/Gerber_V1.2.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freitz85/AppleIISd/b13ed9077f54387077b36edc959048bec4b9f689/Binary/Gerber_V1.2.zip -------------------------------------------------------------------------------- /Binary/ProFile.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freitz85/AppleIISd/b13ed9077f54387077b36edc959048bec4b9f689/Binary/ProFile.zip -------------------------------------------------------------------------------- /Datasheets/104H-TDA0-R.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freitz85/AppleIISd/b13ed9077f54387077b36edc959048bec4b9f689/Datasheets/104H-TDA0-R.pdf -------------------------------------------------------------------------------- /Datasheets/65SPI-B Datasheet V1.1.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freitz85/AppleIISd/b13ed9077f54387077b36edc959048bec4b9f689/Datasheets/65SPI-B Datasheet V1.1.docx -------------------------------------------------------------------------------- /Datasheets/65SPI-B Datasheet V1.1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freitz85/AppleIISd/b13ed9077f54387077b36edc959048bec4b9f689/Datasheets/65SPI-B Datasheet V1.1.pdf -------------------------------------------------------------------------------- /Datasheets/74LS245.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freitz85/AppleIISd/b13ed9077f54387077b36edc959048bec4b9f689/Datasheets/74LS245.pdf -------------------------------------------------------------------------------- /Datasheets/AT28C64.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freitz85/AppleIISd/b13ed9077f54387077b36edc959048bec4b9f689/Datasheets/AT28C64.pdf -------------------------------------------------------------------------------- /Datasheets/AT28C64B.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freitz85/AppleIISd/b13ed9077f54387077b36edc959048bec4b9f689/Datasheets/AT28C64B.pdf -------------------------------------------------------------------------------- /Datasheets/AppleII_Timing.json: -------------------------------------------------------------------------------- 1 | {signal: [ 2 | ['Apple', 3 | {name: '7M', wave: 'n........', period: 2 }, 4 | {name: 'Phi0', wave: 'hl......h......l..', node: '.a......b......c'}, 5 | {name: 'Q3', wave: 'lh...l..h...l..h..'}, 6 | {name: 'ADD', wave: '=.x=............x.', node: '...d............e', phase: 0.5}, 7 | {name: '/DEV_SEL',wave: 'h.......0......1..'}, 8 | {}, 9 | {name: 'R/W', wave: 'x..=.........x....', phase: 0.5}, 10 | {name: 'DATA', wave: 'x........=.......z', node: '.........f.......g', data: 'FromCPU', phase: 0.5}, 11 | {name: 'DATA', wave: 'x..........=....z.', node: '...........h....i', data: 'ToCPU', phase: 0.5}, 12 | ], 13 | 14 | ], 15 | edge: [ 16 | 'a<->b 490 ns', 'a-|>d max 100ns', 'b-|>f max 30ns', 'c-|>e min 15ns', 'h|->c min 140ns', 'c-|>g min 30ns', 'c|->i min 10ns' 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /Datasheets/AppleII_Timing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freitz85/AppleIISd/b13ed9077f54387077b36edc959048bec4b9f689/Datasheets/AppleII_Timing.png -------------------------------------------------------------------------------- /Datasheets/EEPROM_Timing.json: -------------------------------------------------------------------------------- 1 | {signal: [ 2 | ['E2 Read', 3 | {name: 'ADD', wave: 'x.=......x..', node: '..a......b'}, 4 | {name: '/CE', wave: '1..0.....1..', node: '...c'}, 5 | {name: '/OE', wave: '1...0....1..', node: '....d'}, 6 | {name: 'DATA', wave: 'z......=...z', node: '.......e...f'}, 7 | ], 8 | {}, 9 | ['E2 Write', 10 | {name: 'ADD', wave: 'x.=..x........=', node: '..g..h'}, 11 | {name: '/CE', wave: '1.0......1....0', node: '.........i'}, 12 | {name: '/OE', wave: '0.1......0.....'}, 13 | {name: '/WE', wave: '1..0....1.....0', node: '...j....k.....l'}, 14 | {name: 'DATA', wave: 'z....=.....z...', node: '.....m.....n'}, 15 | ], 16 | ], 17 | edge: [ 18 | 'a-|>e max 150ns', 'b-|>f max 50ns', 'c-|>e max 150ns', 'd|->e 10-70ns', 19 | 'g-|>j min 10ns', 'k|->i min 0ns', 'j-|>h min 50ns', 'j->k min 100ns', 'k|->m min 50ns', 'k-|>n min 10ns' 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /Datasheets/EEPROM_Timing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freitz85/AppleIISd/b13ed9077f54387077b36edc959048bec4b9f689/Datasheets/EEPROM_Timing.png -------------------------------------------------------------------------------- /Datasheets/LM1117.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freitz85/AppleIISd/b13ed9077f54387077b36edc959048bec4b9f689/Datasheets/LM1117.pdf -------------------------------------------------------------------------------- /Datasheets/M2716.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freitz85/AppleIISd/b13ed9077f54387077b36edc959048bec4b9f689/Datasheets/M2716.pdf -------------------------------------------------------------------------------- /Datasheets/M2732A.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freitz85/AppleIISd/b13ed9077f54387077b36edc959048bec4b9f689/Datasheets/M2732A.pdf -------------------------------------------------------------------------------- /Datasheets/M48Z12.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freitz85/AppleIISd/b13ed9077f54387077b36edc959048bec4b9f689/Datasheets/M48Z12.pdf -------------------------------------------------------------------------------- /Datasheets/SD Specification - Part 1 Physical Layer Simplified.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freitz85/AppleIISd/b13ed9077f54387077b36edc959048bec4b9f689/Datasheets/SD Specification - Part 1 Physical Layer Simplified.pdf -------------------------------------------------------------------------------- /Datasheets/Timings.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freitz85/AppleIISd/b13ed9077f54387077b36edc959048bec4b9f689/Datasheets/Timings.pptx -------------------------------------------------------------------------------- /Datasheets/Xilinx DS054.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freitz85/AppleIISd/b13ed9077f54387077b36edc959048bec4b9f689/Datasheets/Xilinx DS054.pdf -------------------------------------------------------------------------------- /Datasheets/Xilinx DS057.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freitz85/AppleIISd/b13ed9077f54387077b36edc959048bec4b9f689/Datasheets/Xilinx DS057.pdf -------------------------------------------------------------------------------- /Datasheets/Xilinx XAPP112.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freitz85/AppleIISd/b13ed9077f54387077b36edc959048bec4b9f689/Datasheets/Xilinx XAPP112.pdf -------------------------------------------------------------------------------- /Datasheets/at28c16.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freitz85/AppleIISd/b13ed9077f54387077b36edc959048bec4b9f689/Datasheets/at28c16.pdf -------------------------------------------------------------------------------- /Datasheets/plcc44_bottom.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freitz85/AppleIISd/b13ed9077f54387077b36edc959048bec4b9f689/Datasheets/plcc44_bottom.jpg -------------------------------------------------------------------------------- /Firmware/AppleIISd.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | {9EA7EC3D-1771-420F-932F-231A35ED1200} 28 | MakeFileProj 29 | AppleIISd 30 | 31 | 32 | 33 | Makefile 34 | true 35 | v140 36 | 37 | 38 | Makefile 39 | false 40 | v140 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | __APPLE2__;__APPLE2ENH__;__fastcall__=__fastcall;_MSC_VER=0;__attribute__ 56 | $(PATH);C:\cc65\bin 57 | C:\cc65\include 58 | C:\cc65\lib 59 | 60 | 61 | $(MAKE_HOME)\make OPTIONS=mapfile,listing 62 | $(ProjectDir)\src 63 | $(MAKE_HOME)\make clean 64 | $(MAKE_HOME)\make OPTIONS=mapfile,listing 65 | $(SolutionDir)\ 66 | $(MAKE_HOME)\make clean 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | del /S /Q "$(ProjectDir)makefile.options 75 | $(MAKE_HOME)\make -C "$(ProjectDir)\" PROGRAM="$(ProjectDir)$(Configuration)\$(ProjectName)" 76 | rmdir /S /Q "$(ProjectDir)obj\Win32" 77 | rmdir /S /Q "$(SolutionDir)Release" 78 | del /S /Q "$(ProjectDir)makefile.options 79 | $(MAKE_HOME)\make clean -C "$(ProjectDir)\" PROGRAM="$(ProjectDir)$(Configuration)\$(ProjectName)" 80 | $(MAKE_HOME)\make -C "$(ProjectDir)\" PROGRAM="$(ProjectDir)$(Configuration)\$(ProjectName)" 81 | rmdir /S /Q "$(ProjectDir)obj\Win32" 82 | rmdir /S /Q "$(SolutionDir)Release" 83 | 84 | del /S /Q "$(ProjectDir)makefile.options 85 | $(MAKE_HOME)\make clean -C "$(ProjectDir)\" PROGRAM="$(ProjectDir)$(Configuration)\$(ProjectName)" 86 | rmdir /S /Q "$(ProjectDir)obj\Win32" 87 | rmdir /S /Q "$(SolutionDir)Release" 88 | $(PATH);C:\cc65\bin 89 | $(VC_IncludePath);C:\cc65\include 90 | 91 | C:\cc65\lib 92 | 93 | 94 | $(SolutionDir)$\ 95 | 96 | 97 | 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /Firmware/AppleIISd.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | src 7 | 8 | 9 | src 10 | 11 | 12 | 13 | src 14 | 15 | 16 | src 17 | 18 | 19 | src 20 | 21 | 22 | src 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | {d301b76d-0aac-4430-a25a-193e6e572e60} 31 | 32 | 33 | -------------------------------------------------------------------------------- /Firmware/make_image.bat: -------------------------------------------------------------------------------- 1 | make clean 2 | make OPTIONS=mapfile,listing 3 | java -jar ..\Binary\AppleCommander-ac-1.5.0.jar -d ..\Binary\Flasher.dsk appleiisd.bin 4 | java -jar ..\Binary\AppleCommander-ac-1.5.0.jar -p ..\Binary\Flasher.dsk appleiisd.bin $00 < AppleIISd.bin 5 | copy AppleIISd.bin ..\Binary 6 | -------------------------------------------------------------------------------- /Firmware/make_image.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | make clean 4 | make OPTIONS=mapfile,listing 5 | java -jar ../Binary/AppleCommander-ac-1.5.0.jar -d ../Binary/Flasher.dsk appleiisd.bin 6 | java -jar ../Binary/AppleCommander-ac-1.5.0.jar -p ../Binary/Flasher.dsk appleiisd.bin $00 < AppleIISd.bin 7 | cp AppleIISd.bin ../Binary/ 8 | -------------------------------------------------------------------------------- /Firmware/makefile: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | ### Generic Makefile for cc65 projects - full version with abstract options ### 3 | ### V1.3.0(w) 2010 - 2013 Oliver Schmidt & Patryk "Silver Dream !" ?ogiewa ### 4 | ############################################################################### 5 | 6 | ############################################################################### 7 | ### In order to override defaults - values can be assigned to the variables ### 8 | ############################################################################### 9 | 10 | # Space or comma separated list of cc65 supported target platforms to build for. 11 | # Default: c64 (lowercase!) 12 | TARGETS := apple2enh 13 | 14 | # Name of the final, single-file executable. 15 | # Default: name of the current dir with target name appended 16 | PROGRAM := AppleIISd 17 | 18 | # Path(s) to additional libraries required for linking the program 19 | # Use only if you don't want to place copies of the libraries in SRCDIR 20 | # Default: none 21 | LIBS := 22 | 23 | # Custom linker configuration file 24 | # Use only if you don't want to place it in SRCDIR 25 | # Default: none 26 | CONFIG := 27 | 28 | # Additional C compiler flags and options. 29 | # Default: none 30 | CFLAGS = 31 | 32 | # Additional assembler flags and options. 33 | # Default: none 34 | ASFLAGS = 35 | 36 | # Additional linker flags and options. 37 | # Default: none 38 | LDFLAGS = 39 | 40 | # Path to the directory containing C and ASM sources. 41 | # Default: src 42 | SRCDIR := 43 | 44 | # Path to the directory where object files are to be stored (inside respective target subdirectories). 45 | # Default: obj 46 | OBJDIR := 47 | 48 | # Command used to run the emulator. 49 | # Default: depending on target platform. For default (c64) target: x64 -kernal kernal -VICIIdsize -autoload 50 | EMUCMD := 51 | 52 | # Optional commands used before starting the emulation process, and after finishing it. 53 | # Default: none 54 | # Examples 55 | #PREEMUCMD := osascript -e "tell application \"System Events\" to set isRunning to (name of processes) contains \"X11.bin\"" -e "if isRunning is true then tell application \"X11\" to activate" 56 | #PREEMUCMD := osascript -e "tell application \"X11\" to activate" 57 | #POSTEMUCMD := osascript -e "tell application \"System Events\" to tell process \"X11\" to set visible to false" 58 | #POSTEMUCMD := osascript -e "tell application \"Terminal\" to activate" 59 | PREEMUCMD := 60 | POSTEMUCMD := 61 | 62 | # On Windows machines VICE emulators may not be available in the PATH by default. 63 | # In such case, please set the variable below to point to directory containing 64 | # VICE emulators. 65 | #VICE_HOME := "C:\Program Files\WinVICE-2.2-x86\" 66 | VICE_HOME := 67 | 68 | # Options state file name. You should not need to change this, but for those 69 | # rare cases when you feel you really need to name it differently - here you are 70 | STATEFILE := Makefile.options 71 | 72 | ################################################################################### 73 | #### DO NOT EDIT BELOW THIS LINE, UNLESS YOU REALLY KNOW WHAT YOU ARE DOING! #### 74 | ################################################################################### 75 | 76 | ################################################################################### 77 | ### Mapping abstract options to the actual compiler, assembler and linker flags ### 78 | ### Predefined compiler, assembler and linker flags, used with abstract options ### 79 | ### valid for 2.14.x. Consult the documentation of your cc65 version before use ### 80 | ################################################################################### 81 | 82 | # Compiler flags used to tell the compiler to optimise for SPEED 83 | define _optspeed_ 84 | CFLAGS += -Oris 85 | endef 86 | 87 | # Compiler flags used to tell the compiler to optimise for SIZE 88 | define _optsize_ 89 | CFLAGS += -Or 90 | endef 91 | 92 | # Compiler and assembler flags for generating listings 93 | define _listing_ 94 | CFLAGS += --listing $$(@:.o=.lst) 95 | ASFLAGS += --listing $$(@:.o=.lst) 96 | REMOVES += $(addsuffix .lst,$(basename $(OBJECTS))) 97 | endef 98 | 99 | # Linker flags for generating map file 100 | define _mapfile_ 101 | LDFLAGS += --mapfile $$@.map 102 | REMOVES += $(PROGRAM).map 103 | endef 104 | 105 | # Linker flags for generating VICE label file 106 | define _labelfile_ 107 | LDFLAGS += -Ln $$@.lbl 108 | REMOVES += $(PROGRAM).lbl 109 | endef 110 | 111 | # Linker flags for generating a debug file 112 | define _debugfile_ 113 | LDFLAGS += -Wl --dbgfile,$$@.dbg 114 | REMOVES += $(PROGRAM).dbg 115 | endef 116 | 117 | ############################################################################### 118 | ### Defaults to be used if nothing defined in the editable sections above ### 119 | ############################################################################### 120 | 121 | # Presume the C64 target like the cl65 compile & link utility does. 122 | # Set TARGETS to override. 123 | ifeq ($(TARGETS),) 124 | TARGETS := c64 125 | endif 126 | 127 | # Presume we're in a project directory so name the program like the current 128 | # directory. Set PROGRAM to override. 129 | ifeq ($(PROGRAM),) 130 | PROGRAM := $(notdir $(CURDIR)) 131 | endif 132 | 133 | # Presume the C and asm source files to be located in the subdirectory 'src'. 134 | # Set SRCDIR to override. 135 | ifeq ($(SRCDIR),) 136 | SRCDIR := src 137 | endif 138 | 139 | # Presume the object and dependency files to be located in the subdirectory 140 | # 'obj' (which will be created). Set OBJDIR to override. 141 | ifeq ($(OBJDIR),) 142 | OBJDIR := obj 143 | endif 144 | TARGETOBJDIR := $(OBJDIR) 145 | 146 | # On Windows it is mandatory to have CC65_HOME set. So do not unnecessarily 147 | # rely on cl65 being added to the PATH in this scenario. 148 | ifdef CC65_HOME 149 | CC := $(CC65_HOME)/bin/cl65 150 | else 151 | CC := cl65 152 | endif 153 | 154 | # Default emulator commands and options for particular targets. 155 | # Set EMUCMD to override. 156 | c64_EMUCMD := $(VICE_HOME)x64 -kernal kernal -VICIIdsize -autoload 157 | c128_EMUCMD := $(VICE_HOME)x128 -kernal kernal -VICIIdsize -autoload 158 | vic20_EMUCMD := $(VICE_HOME)xvic -kernal kernal -VICdsize -autoload 159 | pet_EMUCMD := $(VICE_HOME)xpet -Crtcdsize -autoload 160 | plus4_EMUCMD := $(VICE_HOME)xplus4 -TEDdsize -autoload 161 | # So far there is no x16 emulator in VICE (why??) so we have to use xplus4 with -memsize option 162 | c16_EMUCMD := $(VICE_HOME)xplus4 -ramsize 16 -TEDdsize -autoload 163 | cbm510_EMUCMD := $(VICE_HOME)xcbm2 -model 510 -VICIIdsize -autoload 164 | cbm610_EMUCMD := $(VICE_HOME)xcbm2 -model 610 -Crtcdsize -autoload 165 | atari_EMUCMD := atari800 -windowed -xl -pal -nopatchall -run 166 | 167 | ifeq ($(EMUCMD),) 168 | EMUCMD = $($(CC65TARGET)_EMUCMD) 169 | endif 170 | 171 | ############################################################################### 172 | ### The magic begins ### 173 | ############################################################################### 174 | 175 | # The "Native Win32" GNU Make contains quite some workarounds to get along with 176 | # cmd.exe as shell. However it does not provide means to determine that it does 177 | # actually activate those workarounds. Especially $(SHELL) does NOT contain the 178 | # value 'cmd.exe'. So the usual way to determine if cmd.exe is being used is to 179 | # execute the command 'echo' without any parameters. Only cmd.exe will return a 180 | # non-empty string - saying 'ECHO is on/off'. 181 | # 182 | # Many "Native Win32" programs accept '/' as directory delimiter just fine. How- 183 | # ever the internal commands of cmd.exe generally require '\' to be used. 184 | # 185 | # cmd.exe has an internal command 'mkdir' that doesn't understand nor require a 186 | # '-p' to create parent directories as needed. 187 | # 188 | # cmd.exe has an internal command 'del' that reports a syntax error if executed 189 | # without any file so make sure to call it only if there's an actual argument. 190 | ifeq ($(shell echo),) 191 | MKDIR = mkdir -p $1 192 | RMDIR = rmdir $1 193 | RMFILES = $(RM) $1 194 | else 195 | MKDIR = mkdir $(subst /,\,$1) 196 | RMDIR = rmdir $(subst /,\,$1) 197 | RMFILES = $(if $1,del /f $(subst /,\,$1)) 198 | endif 199 | COMMA := , 200 | SPACE := $(N/A) $(N/A) 201 | define NEWLINE 202 | 203 | 204 | endef 205 | # Note: Do not remove any of the two empty lines above ! 206 | 207 | TARGETLIST := $(subst $(COMMA),$(SPACE),$(TARGETS)) 208 | 209 | ifeq ($(words $(TARGETLIST)),1) 210 | 211 | # Set PROGRAM to something like 'myprog.c64'. 212 | override PROGRAM := $(PROGRAM).bin 213 | 214 | # Set SOURCES to something like 'src/foo.c src/bar.s'. 215 | # Use of assembler files with names ending differently than .s is deprecated! 216 | SOURCES := $(wildcard $(SRCDIR)/*.c) 217 | SOURCES += $(wildcard $(SRCDIR)/*.s) 218 | SOURCES += $(wildcard $(SRCDIR)/*.asm) 219 | SOURCES += $(wildcard $(SRCDIR)/*.a65) 220 | 221 | # Add to SOURCES something like 'src/c64/me.c src/c64/too.s'. 222 | # Use of assembler files with names ending differently than .s is deprecated! 223 | SOURCES += $(wildcard $(SRCDIR)/$(TARGETLIST)/*.c) 224 | SOURCES += $(wildcard $(SRCDIR)/$(TARGETLIST)/*.s) 225 | SOURCES += $(wildcard $(SRCDIR)/$(TARGETLIST)/*.asm) 226 | SOURCES += $(wildcard $(SRCDIR)/$(TARGETLIST)/*.a65) 227 | 228 | # Set OBJECTS to something like 'obj/c64/foo.o obj/c64/bar.o'. 229 | OBJECTS := $(addsuffix .o,$(basename $(addprefix $(TARGETOBJDIR)/,$(notdir $(SOURCES))))) 230 | 231 | # Set DEPENDS to something like 'obj/c64/foo.d obj/c64/bar.d'. 232 | DEPENDS := $(OBJECTS:.o=.d) 233 | 234 | # Add to LIBS something like 'src/foo.lib src/c64/bar.lib'. 235 | LIBS += $(wildcard $(SRCDIR)/*.lib) 236 | LIBS += $(wildcard $(SRCDIR)/$(TARGETLIST)/*.lib) 237 | 238 | # Add to CONFIG something like 'src/c64/bar.cfg src/foo.cfg'. 239 | CONFIG += $(wildcard $(SRCDIR)/$(TARGETLIST)/*.cfg) 240 | CONFIG += $(wildcard $(SRCDIR)/*.cfg) 241 | 242 | # Select CONFIG file to use. Target specific configs have higher priority. 243 | ifneq ($(word 2,$(CONFIG)),) 244 | CONFIG := $(firstword $(CONFIG)) 245 | $(info Using config file $(CONFIG) for linking) 246 | endif 247 | 248 | .SUFFIXES: 249 | .PHONY: all test clean zap love 250 | 251 | all: $(PROGRAM) 252 | 253 | -include $(DEPENDS) 254 | -include $(STATEFILE) 255 | 256 | # If OPTIONS are given on the command line then save them to STATEFILE 257 | # if (and only if) they have actually changed. But if OPTIONS are not 258 | # given on the command line then load them from STATEFILE. Have object 259 | # files depend on STATEFILE only if it actually exists. 260 | ifeq ($(origin OPTIONS),command line) 261 | ifneq ($(OPTIONS),$(_OPTIONS_)) 262 | ifeq ($(OPTIONS),) 263 | $(info Removing OPTIONS) 264 | $(shell $(RM) $(STATEFILE)) 265 | $(eval $(STATEFILE):) 266 | else 267 | $(info Saving OPTIONS=$(OPTIONS)) 268 | $(shell echo _OPTIONS_=$(OPTIONS) > $(STATEFILE)) 269 | endif 270 | $(eval $(OBJECTS): $(STATEFILE)) 271 | endif 272 | else 273 | ifeq ($(origin _OPTIONS_),file) 274 | $(info Using saved OPTIONS=$(_OPTIONS_)) 275 | OPTIONS = $(_OPTIONS_) 276 | $(eval $(OBJECTS): $(STATEFILE)) 277 | endif 278 | endif 279 | 280 | # Transform the abstract OPTIONS to the actual cc65 options. 281 | $(foreach o,$(subst $(COMMA),$(SPACE),$(OPTIONS)),$(eval $(_$o_))) 282 | 283 | # Strip potential variant suffix from the actual cc65 target. 284 | CC65TARGET := $(firstword $(subst .,$(SPACE),$(TARGETLIST))) 285 | 286 | # The remaining targets. 287 | $(TARGETOBJDIR): 288 | $(call MKDIR,$@) 289 | 290 | vpath %.c $(SRCDIR)/$(TARGETLIST) $(SRCDIR) 291 | 292 | $(TARGETOBJDIR)/%.o: %.c | $(TARGETOBJDIR) 293 | $(CC) -t $(CC65TARGET) -c --create-dep $(@:.o=.d) $(CFLAGS) -o $@ $< 294 | 295 | vpath %.s $(SRCDIR)/$(TARGETLIST) $(SRCDIR) 296 | 297 | $(TARGETOBJDIR)/%.o: %.s | $(TARGETOBJDIR) 298 | $(CC) -t $(CC65TARGET) -c --create-dep $(@:.o=.d) $(ASFLAGS) -o $@ $< 299 | 300 | vpath %.asm $(SRCDIR)/$(TARGETLIST) $(SRCDIR) 301 | 302 | $(TARGETOBJDIR)/%.o: %.asm | $(TARGETOBJDIR) 303 | $(CC) -t $(CC65TARGET) -c --create-dep $(@:.o=.d) $(ASFLAGS) -o $@ $< 304 | 305 | vpath %.a65 $(SRCDIR)/$(TARGETLIST) $(SRCDIR) 306 | 307 | $(TARGETOBJDIR)/%.o: %.a65 | $(TARGETOBJDIR) 308 | $(CC) -t $(CC65TARGET) -c --create-dep $(@:.o=.d) $(ASFLAGS) -o $@ $< 309 | 310 | $(PROGRAM): $(CONFIG) $(OBJECTS) $(LIBS) 311 | $(CC) -t $(CC65TARGET) $(LDFLAGS) -o $@ $(patsubst %.cfg,-C %.cfg,$^) 312 | 313 | test: $(PROGRAM) 314 | $(PREEMUCMD) 315 | $(EMUCMD) $< 316 | $(POSTEMUCMD) 317 | 318 | clean: 319 | $(call RMFILES,$(OBJECTS)) 320 | $(call RMFILES,$(DEPENDS)) 321 | $(call RMFILES,$(REMOVES)) 322 | $(call RMFILES,$(PROGRAM)) 323 | 324 | else # $(words $(TARGETLIST)),1 325 | 326 | all test clean: 327 | $(foreach t,$(TARGETLIST),$(MAKE) TARGETS=$t $@$(NEWLINE)) 328 | 329 | endif # $(words $(TARGETLIST)),1 330 | 331 | OBJDIRLIST := $(wildcard $(OBJDIR)/*) 332 | 333 | zap: 334 | $(foreach o,$(OBJDIRLIST),-$(call RMFILES,$o/*.o $o/*.d $o/*.lst)$(NEWLINE)) 335 | $(foreach o,$(OBJDIRLIST),-$(call RMDIR,$o)$(NEWLINE)) 336 | -$(call RMDIR,$(OBJDIR)) 337 | -$(call RMFILES,$(basename $(PROGRAM)).* $(STATEFILE)) 338 | 339 | love: 340 | @echo "Not war, eh?" 341 | 342 | ################################################################### 343 | ### Place your additional targets in the additional Makefiles ### 344 | ### in the same directory - their names have to end with ".mk"! ### 345 | ################################################################### 346 | -include *.mk -------------------------------------------------------------------------------- /Firmware/src/AppleIISd.cfg: -------------------------------------------------------------------------------- 1 | # Configuration for assembler programs which don't need a special setup 2 | 3 | FEATURES { 4 | STARTADDRESS: default = $0803; 5 | } 6 | MEMORY { 7 | ZP: file = "", start = $0000, size = $00FF; 8 | HEADER: file = %O, start = %S - 4, size = $0004; 9 | MAIN: file = %O, define = yes, start = %S, size = $C000 - %S; 10 | BSS: file = "", start = __MAIN_LAST__, size = $C000 - __MAIN_LAST__; 11 | 12 | SLOTROM: file = %O, fill = yes start = $C700, size = $00FB; 13 | SLOTID: file = %O, start = $C7FB, size = $0005; 14 | EXTROM: file = %O, fill = yes start = $C800, size = $0700; 15 | } 16 | SEGMENTS { 17 | ZEROPAGE: load = ZP, type = zp, optional = yes; 18 | EXEHDR: load = HEADER, type = ro, optional = yes; 19 | CODE: load = MAIN, type = rw; 20 | RODATA: load = MAIN, type = ro, optional = yes; 21 | DATA: load = MAIN, type = rw, optional = yes; 22 | BSS: load = BSS, type = bss, optional = yes, define = yes; 23 | 24 | SLOTROM: load = SLOTROM, type = ro; 25 | SLOTID: load = SLOTID, type = ro; 26 | EXTROM: load = EXTROM, type = ro, optional = yes; 27 | } 28 | -------------------------------------------------------------------------------- /Firmware/src/AppleIISd.inc: -------------------------------------------------------------------------------- 1 | ;******************************* 2 | ; 3 | ; Apple][Sd Firmware 4 | ; Version 1.2.3 5 | ; Defines 6 | ; 7 | ; (c) Florian Reitz, 2017 - 2021 8 | ; 9 | ; X register usually contains SLOT16 10 | ; Y register is used for counting or SLOT 11 | ; 12 | ;******************************* 13 | 14 | ; ZP locations 15 | PSAVE := $3D ; P save location 16 | SLOT16 := $3E ; $s0 -> slot * 16 17 | SLOT := $3F ; $0s 18 | CMDLO := $40 19 | CMDHI := $41 20 | PDZPAREA = PSAVE 21 | PDZPSIZE = CMDHI-PDZPAREA+1 22 | 23 | ; ProDOS 24 | DCMD := $42 ; Command code 25 | DSNUMBER := $43 ; drive / slot number 26 | BUFFER := $44 ; buffer pointer, two bytes 27 | BLOCKNUM := $46 ; block number, two bytes 28 | 29 | ; Smartport 30 | SMPARAMLIST := $48 ; parameter list, two bytes 31 | SMCMDLIST := $4A ; command list, two bytes 32 | SMCSCODE := $4C 33 | SMZPAREA = SMPARAMLIST 34 | SMZPSIZE = SMCSCODE-SMZPAREA+1 35 | SMCMD = DCMD 36 | 37 | 38 | ; Ram equates, access with SLOT offset 39 | R30 := $0478 40 | R31 := $04F8 41 | R32 := $0578 42 | R33 := $05F8 43 | DRVNUM := $0678 44 | CURSLOT := $07F8 ; $Cs 45 | 46 | ; Rom equates 47 | OAPPLE := $C061 ; open apple key 48 | DATA := $C080 49 | CTRL := DATA+1 50 | SS := DATA+3 51 | 52 | ; Constants 53 | DUMMY = $FF 54 | FRX = $10 ; CTRL register 55 | ECE = $04 56 | SS0 = $01 ; SS register 57 | SDHC = $10 58 | WP = $20 59 | CD = $40 60 | CARD_INIT = $80 61 | 62 | SMDRIVERVER = $120B ; Version 1.2 Beta 63 | 64 | ; Error codes 65 | NO_ERR = $00 66 | ERR_BADCMD = $01 67 | ERR_BADPCNT = $04 68 | ERR_BUSERR = $06 69 | ERR_BADUNIT = $11 70 | ERR_NOINT = $1F 71 | ERR_BADCTL = $21 72 | ERR_BADCTLPARM = $22 73 | ERR_IOERR = $27 74 | ERR_NODRIVE = $28 75 | ERR_NOWRITE = $2B 76 | ERR_BADBLOCK = $2D 77 | ERR_OFFLINE = $2F 78 | -------------------------------------------------------------------------------- /Firmware/src/AppleIISd.s: -------------------------------------------------------------------------------- 1 | ;******************************* 2 | ; 3 | ; Apple][Sd Firmware 4 | ; Version 1.2.3 5 | ; Main source 6 | ; 7 | ; (c) Florian Reitz, 2017 - 2021 8 | ; 9 | ; X register usually contains SLOT16 10 | ; Y register is used for counting or SLOT 11 | ; 12 | ;******************************* 13 | 14 | .export INIT 15 | 16 | .import PRODOS 17 | .import SMARTPORT 18 | .import GETR1 19 | .import GETR3 20 | .import SDCMD 21 | .import CARDDET 22 | .import INITED 23 | .import READ 24 | 25 | .include "AppleIISd.inc" 26 | 27 | 28 | ;******************************* 29 | ; 30 | ; Signature bytes 31 | ; 32 | ; 65535 blocks 33 | ; Removable media 34 | ; Non-interruptable 35 | ; 2 drives 36 | ; Read, write and status allowed 37 | ; 38 | ;******************************* 39 | 40 | .segment "SLOTID" 41 | .byt $0 ; not extended, no SCSI, no RAM 42 | .word $0000 ; use status call 43 | .byt $97 ; Status bits 44 | .byt CMD0 243 | STA CMDHI 244 | JSR SDCMD 245 | JSR GETR1 ; get response 246 | CMP #$01 247 | BNE @ERROR1 ; error! 248 | 249 | LDA #CMD8 252 | STA CMDHI 253 | JSR SDCMD 254 | JSR GETR3 ; R7 is also 1+4 bytes 255 | CMP #$01 256 | BNE @SDV1 ; may be SD Ver. 1 257 | 258 | LDY SLOT ; check for $aa in R33 259 | LDA R33,Y 260 | CMP #$AA 261 | BNE @ERROR1 ; error! 262 | 263 | @SDV2: LDA #CMD55 266 | STA CMDHI 267 | JSR SDCMD 268 | JSR GETR1 269 | LDA #ACMD4140 272 | STA CMDHI 273 | JSR SDCMD 274 | JSR GETR1 275 | CMP #$01 276 | BEQ @SDV2 ; wait for ready 277 | CMP #0 278 | BNE @ERROR1 ; error! 279 | 280 | ; SD Ver. 2 initialized! 281 | LDA #CMD58 284 | STA CMDHI 285 | JSR SDCMD 286 | JSR GETR3 287 | CMP #0 288 | BNE @ERROR1 ; error! 289 | LDY SLOT 290 | LDA R30,Y 291 | AND #$40 ; check CCS 292 | BEQ @BLOCKSZ 293 | 294 | LDA SS,X ; card is SDHC 295 | ORA #SDHC 296 | STA SS,X 297 | JMP @END 298 | 299 | @ERROR1: JMP @IOERROR ; needed for far jump 300 | 301 | @SDV1: LDA #CMD55 304 | STA CMDHI 305 | JSR SDCMD ; ignore response 306 | LDA #ACMD410 309 | STA CMDHI 310 | JSR SDCMD 311 | JSR GETR1 312 | CMP #$01 313 | BEQ @SDV1 ; wait for ready 314 | CMP #0 315 | BNE @MMC ; may be MMC card 316 | ; SD Ver. 1 initialized! 317 | JMP @BLOCKSZ 318 | 319 | @MMC: LDA #CMD1 322 | STA CMDHI 323 | @LOOP1: JSR SDCMD 324 | JSR GETR1 325 | CMP #$01 326 | BEQ @LOOP1 ; wait for ready 327 | CMP #0 328 | BNE @IOERROR ; error! 329 | ; MMC Ver. 3 initialized! 330 | 331 | @BLOCKSZ: LDA #CMD16 334 | STA CMDHI 335 | JSR SDCMD 336 | JSR GETR1 337 | CMP #0 338 | BNE @IOERROR ; error! 339 | 340 | @END: LDA SS,X 341 | ORA #CARD_INIT ; initialized 342 | STA SS,X 343 | LDA CTRL,X 344 | ORA #ECE ; enable 7MHz 345 | STA CTRL,X 346 | CLC ; all ok 347 | LDY #NO_ERR 348 | BCC @END1 349 | 350 | @IOERROR: SEC 351 | LDY #ERR_IOERR ; init error 352 | @END1: LDA SS,X ; set CS high 353 | ORA #SS0 354 | STA SS,X 355 | TYA ; retval in A 356 | KNOWNRTS: RTS 357 | 358 | 359 | TEXT: .asciiz " Apple][Sd v1.2.2 (c)2021 Florian Reitz" 360 | .assert(*-TEXT)=40, error, "TEXT must be 40 bytes long" 361 | 362 | 363 | CMD0: .byt $40, $00, $00 364 | .byt $00, $00, $95 365 | CMD1: .byt $41, $00, $00 366 | .byt $00, $00, $F9 367 | CMD8: .byt $48, $00, $00 368 | .byt $01, $AA, $87 369 | CMD16: .byt $50, $00, $00 370 | .byt $02, $00, $FF 371 | CMD55: .byt $77, $00, $00 372 | .byt $00, $00, $FF 373 | CMD58: .byt $7A, $00, $00 374 | .byt $00, $00, $FF 375 | ACMD4140: .byt $69, $40, $00 376 | .byt $00, $00, $77 377 | ACMD410: .byt $69, $00, $00 378 | .byt $00, $00, $FF 379 | -------------------------------------------------------------------------------- /Firmware/src/Helper.s: -------------------------------------------------------------------------------- 1 | ;******************************* 2 | ; 3 | ; Apple][Sd Firmware 4 | ; Version 1.2.3 5 | ; Helper functions 6 | ; 7 | ; (c) Florian Reitz, 2017 - 2021 8 | ; 9 | ; X register usually contains SLOT16 10 | ; Y register is used for counting or SLOT 11 | ; 12 | ;******************************* 13 | 14 | .export SDCMD 15 | .export GETR1 16 | .export GETR3 17 | .export GETBLOCK 18 | .export COMMAND 19 | .export CARDDET 20 | .export WRPROT 21 | .export INITED 22 | 23 | 24 | .include "AppleIISd.inc" 25 | .segment "EXTROM" 26 | 27 | 28 | ;******************************* 29 | ; 30 | ; Send SD command 31 | ; Call with command in CMDHI and CMDLO 32 | ; 33 | ;******************************* 34 | 35 | SDCMD: PHY 36 | LDY #0 37 | @LOOP: LDA (CMDLO),Y 38 | STA DATA,X 39 | @WAIT: LDA CTRL,X ; TC is in N 40 | BPL @WAIT 41 | INY 42 | CPY #6 43 | BCC @LOOP 44 | PLY 45 | RTS 46 | 47 | 48 | ;******************************* 49 | ; 50 | ; Get R1 51 | ; R1 is in A 52 | ; 53 | ;******************************* 54 | 55 | GETR1: LDA #DUMMY 56 | STA DATA,X 57 | @WAIT: LDA CTRL,X 58 | BPL @WAIT 59 | LDA DATA,X ; get response 60 | BMI GETR1 ; wait for MSB=0 61 | PHA 62 | LDA #DUMMY 63 | STA DATA,X ; send another dummy 64 | PLA ; restore R1 65 | RTS 66 | 67 | ;******************************* 68 | ; 69 | ; Get R3 or R7 70 | ; R1 is in A 71 | ; R3 is in scratchpad ram 72 | ; 73 | ;******************************* 74 | 75 | GETR3: JSR GETR1 ; get R1 first 76 | PHA ; save R1 77 | PHY ; save Y 78 | LDY #04 ; load counter 79 | JMP @WAIT ; first byte is already there 80 | @LOOP: LDA #DUMMY ; send dummy 81 | STA DATA,X 82 | @WAIT: LDA CTRL,X 83 | BPL @WAIT 84 | LDA DATA,X 85 | PHA 86 | DEY 87 | BNE @LOOP ; do 4 times 88 | LDY SLOT 89 | PLA 90 | STA R33,Y ; save R3 91 | PLA 92 | STA R32,Y 93 | PLA 94 | STA R31,Y 95 | PLA 96 | STA R30,Y ; R30 is MSB 97 | PLY ; restore Y 98 | LDA #DUMMY 99 | STA DATA,X ; send another dummy 100 | PLA ; restore R1 101 | RTS 102 | 103 | 104 | ;******************************* 105 | ; 106 | ; Calculate block address 107 | ; Unit number is in $43 DSSS0000 108 | ; Block no is in $46-47 109 | ; Address is in R30-R33 110 | ; 111 | ;******************************* 112 | 113 | GETBLOCK: PHX ; save X 114 | PHY ; save Y 115 | LDX SLOT ; SLOT is now in X 116 | LDY SLOT16 117 | LDA BLOCKNUM ; store block num 118 | STA R33,X ; in R30-R33 119 | LDA BLOCKNUM+1 120 | STA R32,X 121 | STZ R31,X 122 | STZ R30,X 123 | 124 | TYA ; get SLOT16 125 | EOR DSNUMBER 126 | AND #$70 ; check only slot bits 127 | BEQ @DRIVE ; it is our slot 128 | LDA #2 ; it is a phantom slot 129 | STA R31,X 130 | 131 | @DRIVE: LDA DSNUMBER ; drive number 132 | BPL @SDHC ; D1 133 | LDA R31,X ; D2 134 | INC A 135 | STA R31,X 136 | 137 | @SDHC: LDA #SDHC 138 | AND SS,Y ; if card is SDHC, 139 | BNE @END ; use block addressing 140 | 141 | LDY #9 ; ASL can't be used with Y 142 | @LOOP: ASL R33,X ; mul block num 143 | ROL R32,X ; by 512 to get 144 | ROL R31,X ; real address 145 | ROL R30,X 146 | DEY 147 | BNE @LOOP 148 | 149 | @END: PLY ; restore Y 150 | PLX ; restore X 151 | RTS 152 | 153 | 154 | ;******************************* 155 | ; 156 | ; Send SD command 157 | ; Cmd is in A 158 | ; 159 | ;******************************* 160 | 161 | COMMAND: PHY ; save Y 162 | LDY SLOT 163 | STA DATA,X ; send command 164 | LDA R30,Y ; get arg from R30 on 165 | STA DATA,X 166 | LDA R31,Y 167 | STA DATA,X 168 | LDA R32,Y 169 | STA DATA,X 170 | LDA R33,Y 171 | STA DATA,X 172 | LDA #DUMMY 173 | STA DATA,X ; dummy crc 174 | JSR GETR1 175 | PLY ; restore Y 176 | RTS 177 | 178 | 179 | ;******************************* 180 | ; 181 | ; Check for card detect 182 | ; X must contain SLOT16 183 | ; 184 | ; C Clear - card in slot 185 | ; Set - no card in slot 186 | ; 187 | ;******************************* 188 | 189 | CARDDET: PHA 190 | LDA #CD ; 0: card in 191 | BIT SS,X ; 1: card out 192 | CLC 193 | BEQ @DONE ; card is in 194 | SEC ; card is out 195 | @DONE: PLA 196 | RTS 197 | 198 | 199 | ;******************************* 200 | ; 201 | ; Check for write protect 202 | ; X must contain SLOT16 203 | ; 204 | ; C Clear - card not protected 205 | ; Set - card write protected 206 | ; 207 | ;******************************* 208 | 209 | WRPROT: PHA 210 | LDA #WP ; 0: write enabled 211 | BIT SS,X ; 1: write disabled 212 | CLC 213 | BEQ @DONE 214 | SEC 215 | @DONE: PLA 216 | RTS 217 | 218 | 219 | ;******************************* 220 | ; 221 | ; Check if card is initialized 222 | ; X must contain SLOT16 223 | ; 224 | ; C Clear - card initialized 225 | ; Set - card not initialized 226 | ; 227 | ;******************************* 228 | 229 | INITED: PHA 230 | LDA #CARD_INIT ; 0: card not initialized 231 | BIT SS,X ; 1: card initialized 232 | CLC 233 | BNE @DONE 234 | SEC 235 | @DONE: PLA 236 | RTS 237 | -------------------------------------------------------------------------------- /Firmware/src/ProDOS.s: -------------------------------------------------------------------------------- 1 | ;******************************* 2 | ; 3 | ; Apple][Sd Firmware 4 | ; Version 1.2.3 5 | ; ProDOS functions 6 | ; 7 | ; (c) Florian Reitz, 2017 - 2021 8 | ; 9 | ; X register usually contains SLOT16 10 | ; Y register is used for counting or SLOT 11 | ; 12 | ;******************************* 13 | 14 | .export PRODOS 15 | .export STATUS 16 | .export READ 17 | .export WRITE 18 | 19 | .import COMMAND 20 | .import SDCMD 21 | .import GETBLOCK 22 | .import CARDDET 23 | .import INITED 24 | .import INIT 25 | .import WRPROT 26 | .import GETR1 27 | .import GETR3 28 | 29 | .include "AppleIISd.inc" 30 | .segment "EXTROM" 31 | 32 | 33 | ;******************************* 34 | ; 35 | ; ProDOS command dispatcher 36 | ; 37 | ; $42-$47 MLI input locations 38 | ; X Slot*16 39 | ; Y Slot 40 | ; 41 | ; C Clear - No error 42 | ; Set - Error 43 | ; A $00 - No error 44 | ; $01 - Unknown command 45 | ; 46 | ;******************************* 47 | 48 | PRODOS: LDA DCMD ; get command 49 | BEQ @STATUS ; branch if cmd is 0 50 | CMP #1 51 | BEQ @READ 52 | CMP #2 53 | BEQ @WRITE 54 | LDA #ERR_BADCMD ; unknown command 55 | SEC 56 | RTS 57 | 58 | @STATUS: JMP STATUS 59 | @READ: JMP READ 60 | @WRITE: JMP WRITE 61 | 62 | 63 | ;******************************* 64 | ; 65 | ; Status request 66 | ; $43 Unit number DSSS000 67 | ; $44-45 Unused 68 | ; $46-47 Unused 69 | ; 70 | ; C Clear - No error 71 | ; Set - Error 72 | ; A $00 - No error 73 | ; $28 - No card inserted 74 | ; $2B - Card write protected 75 | ; X - Blocks avail (low byte) 76 | ; Y - Blocks avail (high byte) 77 | ; 78 | ;******************************* 79 | 80 | STATUS: LDA #NO_ERR ; Thanks for this one, Antoine! 81 | JSR CARDDET 82 | BCC @WRPROT 83 | LDA #ERR_NODRIVE; no card inserted 84 | BNE @DONE 85 | 86 | @WRPROT: JSR WRPROT 87 | BCC @DONE 88 | LDA #ERR_NOWRITE; card write protected 89 | 90 | @DONE: LDX #$FF ; 32 MB partition 91 | LDY #$FF 92 | RTS 93 | 94 | 95 | ;******************************* 96 | ; 97 | ; Read 512 byte block 98 | ; $43 Unit number DSSS0000 99 | ; $44-45 Address (LO/HI) of buffer 100 | ; $46-47 Block number (LO/HI) 101 | ; 102 | ; C Clear - No error 103 | ; Set - Error 104 | ; A $00 - No error 105 | ; $27 - Bad block number 106 | ; $28 - No card inserted 107 | ; 108 | ;******************************* 109 | 110 | READ: JSR CARDDET ; check for card 111 | BCS @NDERROR ; no card 112 | 113 | JSR INITED ; check for initialization 114 | BCC @GETBLOCK 115 | 116 | JSR INIT ; initialize card 117 | BCS @NDERROR ; init failed 118 | 119 | @GETBLOCK: JSR GETBLOCK ; calc block address 120 | 121 | LDA SS,X ; enable /CS 122 | AND #<~SS0 123 | STA SS,X 124 | LDA #$51 ; send CMD17 125 | JSR COMMAND ; send command 126 | CMP #0 127 | BNE @IOERROR ; check for error 128 | 129 | @GETTOK: LDA #DUMMY ; get data token 130 | STA DATA,X 131 | LDA DATA,X ; get response 132 | CMP #$FE 133 | BNE @GETTOK ; wait for $FE 134 | 135 | LDA CTRL,X ; enable FRX 136 | ORA #FRX 137 | STA CTRL,X 138 | LDA #DUMMY 139 | STA DATA,X 140 | 141 | LDY #0 142 | @LOOP1: LDA DATA,X ; read data from card 143 | STA (BUFFER),Y 144 | INY 145 | BNE @LOOP1 146 | INC BUFFER+1 ; inc msb on page boundary 147 | @LOOP2: LDA DATA,X 148 | STA (BUFFER),Y 149 | INY 150 | BNE @LOOP2 151 | DEC BUFFER+1 152 | 153 | @CRC: LDA DATA,X ; read two bytes crc 154 | LDA DATA,X ; and ignore 155 | LDA DATA,X ; read a dummy byte 156 | 157 | LDA CTRL,X ; disable FRX 158 | AND #<~FRX 159 | STA CTRL,X 160 | CLC ; no error 161 | LDA #NO_ERR 162 | 163 | @DONE: PHP 164 | PHA 165 | LDA SS,X 166 | ORA #SS0 167 | STA SS,X ; disable /CS 168 | PLA 169 | PLP 170 | RTS 171 | 172 | @IOERROR: SEC ; an error occured 173 | LDA #ERR_IOERR 174 | BRA @DONE 175 | 176 | @NDERROR: SEC ; an error occured 177 | LDA #ERR_NODRIVE 178 | BRA @DONE 179 | 180 | 181 | ;******************************* 182 | ; 183 | ; Write 512 byte block 184 | ; $43 Unit number DSSS0000 185 | ; $44-45 Address (LO/HI) of buffer 186 | ; $46-47 Block number (LO/HI) 187 | ; 188 | ; C Clear - No error 189 | ; Set - Error 190 | ; A $00 - No error 191 | ; $27 - I/O error or bad block number 192 | ; $2B - Card write protected 193 | ; 194 | ;******************************* 195 | 196 | WRITE: JSR WRPROT 197 | BCS @WPERROR ; card write protected 198 | 199 | JSR GETBLOCK ; calc block address 200 | 201 | LDA SS,X ; enable /CS 202 | AND #<~SS0 203 | STA SS,X 204 | LDA #$58 ; send CMD24 205 | JSR COMMAND ; send command 206 | CMP #0 207 | BNE @IOERROR ; check for error 208 | 209 | LDA #DUMMY 210 | STA DATA,X ; send dummy 211 | LDA #$FE 212 | STA DATA,X ; send data token 213 | 214 | LDY #0 215 | @LOOP1: LDA (BUFFER),Y 216 | STA DATA,X 217 | INY 218 | BNE @LOOP1 219 | INC BUFFER+1 220 | @LOOP2: LDA (BUFFER),Y 221 | STA DATA,X 222 | INY 223 | BNE @LOOP2 224 | DEC BUFFER+1 225 | 226 | @CRC: LDA #DUMMY 227 | STA DATA,X ; send 2 dummy crc bytes 228 | STA DATA,X 229 | 230 | STA DATA,X ; get data response 231 | LDA DATA,X 232 | AND #$1F 233 | CMP #$05 234 | BNE @IOERROR ; check for write error 235 | CLC ; no error 236 | LDA #NO_ERR 237 | 238 | @DONE: PHP 239 | PHA 240 | @WAIT: LDA #DUMMY 241 | STA DATA,X ; wait for write cycle 242 | LDA DATA,X ; to complete 243 | BEQ @WAIT 244 | 245 | LDA SS,X ; disable /CS 246 | ORA #SS0 247 | STA SS,X 248 | PLA 249 | PLP 250 | RTS 251 | 252 | @IOERROR: SEC ; an error occured 253 | LDA #ERR_IOERR 254 | BRA @DONE 255 | 256 | @WPERROR: SEC 257 | LDA #ERR_NOWRITE 258 | BRA @DONE 259 | -------------------------------------------------------------------------------- /Firmware/src/Smartport.s: -------------------------------------------------------------------------------- 1 | ;******************************* 2 | ; 3 | ; Apple][Sd Firmware 4 | ; Version 1.2.3 5 | ; Smartport functions 6 | ; 7 | ; (c) Florian Reitz, 2017 - 2021 8 | ; 9 | ; X register usually contains SLOT16 10 | ; Y register is used for counting or SLOT 11 | ; 12 | ;******************************* 13 | 14 | .export SMARTPORT 15 | 16 | .import READ 17 | .import WRITE 18 | .import CARDDET 19 | .import WRPROT 20 | 21 | .include "AppleIISd.inc" 22 | .segment "EXTROM" 23 | 24 | 25 | ;******************************* 26 | ; 27 | ; Smartport command dispatcher 28 | ; 29 | ; $42-$47 MLI input locations 30 | ; X Slot*16 31 | ; Y Slot 32 | ; 33 | ; C Clear - No error 34 | ; Set - Error 35 | ; A $00 - No error 36 | ; $01 - Unknown command 37 | ; 38 | ;******************************* 39 | 40 | SMARTPORT: LDY #SMZPSIZE-1 ; save zeropage area for Smarport 41 | @SAVEZP: LDA SMZPAREA,Y 42 | PHA 43 | DEY 44 | BPL @SAVEZP 45 | 46 | TSX ; get call address 47 | LDA $103+PDZPSIZE+SMZPSIZE,X 48 | STA SMPARAMLIST ; store temporarily 49 | CLC 50 | ADC #3 ; adjust return address 51 | STA $103+PDZPSIZE+SMZPSIZE,X 52 | LDA $104+PDZPSIZE+SMZPSIZE,X 53 | STA SMPARAMLIST+1 54 | ADC #0 55 | STA $104+PDZPSIZE+SMZPSIZE,X 56 | 57 | LDY #1 ; get command code 58 | LDA (SMPARAMLIST),Y 59 | STA SMCMD 60 | INY 61 | LDA (SMPARAMLIST),Y 62 | TAX 63 | INY 64 | LDA (SMPARAMLIST),Y 65 | STA SMPARAMLIST+1 ; is now parameter list 66 | STX SMPARAMLIST 67 | 68 | LDA #ERR_BADCMD ; suspect bad command 69 | LDX SMCMD 70 | CPX #$09+1 ; command too large 71 | BCS @END 72 | 73 | LDA (SMPARAMLIST) ; parameter count 74 | CMP REQPARAMCOUNT,X 75 | BNE @COUNTMISMATCH 76 | 77 | LDY #1 ; get drive number 78 | LDA (SMPARAMLIST),Y 79 | LDY SLOT 80 | STA DRVNUM,Y 81 | 82 | TXA ; SMCMD 83 | ASL A ; shift for use of word addresses 84 | TAX 85 | JSR @JMPSPCOMMAND ; Y holds SLOT 86 | BCS @END ; jump on error 87 | LDA #NO_ERR 88 | 89 | @END: TAX ; save retval 90 | LDY #0 ; restore zeropage 91 | @RESTZP: PLA 92 | STA SMZPAREA,Y 93 | INY 94 | CPY #SMZPSIZE 95 | BCC @RESTZP 96 | 97 | TXA 98 | ;warum feste anzahl an bytes f�r return wert? 99 | LDY #2 ; highbyte of # bytes transferred 100 | LDX #0 ; low byte of # bytes transferred 101 | ;warum wird mit #1 verglichen? 102 | CMP #1 ; C=1 if A != NO_ERR 103 | RTS 104 | 105 | @COUNTMISMATCH: 106 | LDA #ERR_BADPCNT 107 | BRA @END 108 | 109 | @JMPSPCOMMAND: ; use offset from cmd*2 110 | JMP (SPDISPATCH,X) 111 | 112 | 113 | 114 | ; Smartport Status command 115 | ; 116 | SMSTATUS: JSR GETCSLIST 117 | LDY SLOT 118 | LDA DRVNUM,Y 119 | BNE @PARTITION ; status call for a partition 120 | 121 | LDA SMCSCODE 122 | BEQ @STATUS00 ; status call 0 for the bus 123 | LDA #ERR_BADCTL ; calls other than 0 are not allowed 124 | SEC 125 | RTS 126 | 127 | ; TODO support partitions based on card size 128 | @STATUS00: LDA #4 ; support 4 partitions 129 | STA (SMCMDLIST) 130 | 131 | LDY #7 132 | @LOOP00: LDA STATUS00DATA-1,Y 133 | STA (SMCMDLIST),Y 134 | DEY 135 | BNE @LOOP00 136 | CLC 137 | RTS 138 | 139 | @PARTITION: LDX SMCSCODE 140 | BEQ @STATUS03 ; 0: device status 141 | DEX 142 | BEQ @GETDCB ; 1: get DCB 143 | DEX 144 | DEX 145 | BEQ @STATUS03 ; 3: get DIB 146 | LDA #ERR_BADCTL 147 | SEC 148 | RTS 149 | 150 | @GETDCB: LDA #1 ; return 'empty' DCB, one byte 151 | STA (SMCMDLIST) 152 | TAY 153 | LDA #NO_ERR 154 | STA (SMCMDLIST),Y 155 | CLC 156 | RTS 157 | 158 | @STATUS03: LDA #$E8 ; block device, read, write, format, 159 | ; not online, no write-protect 160 | LDX SLOT16 161 | JSR CARDDET 162 | BCS @WRPROT 163 | ORA #$10 ; card inserted 164 | @WRPROT: JSR WRPROT 165 | BCC @STATUSBYTE 166 | ORA #$04 ; SD card write-protected 167 | @STATUSBYTE:STA (SMCMDLIST) 168 | 169 | LDY #1 ; block count, always $00FFFF 170 | LDA #$FF 171 | STA (SMCMDLIST),Y 172 | INY 173 | STA (SMCMDLIST),Y 174 | INY 175 | LDA #0 176 | STA (SMCMDLIST),Y 177 | 178 | LDA SMCSCODE 179 | BEQ @DONE ; done if code 0, else get DIB, 21 bytes 180 | 181 | LDY #4 182 | @LOOP: LDA STATUS3DATA-4,Y 183 | STA (SMCMDLIST),Y 184 | INY 185 | CPY #21+4 186 | BCC @LOOP 187 | 188 | @DONE: CLC 189 | RTS 190 | 191 | 192 | ; Smartport Control command 193 | ; 194 | ; no controls supported, yet 195 | ; 196 | SMCONTROL: JSR GETCSLIST 197 | LDX SMCSCODE 198 | BEQ @RESET ; 0: Reset 199 | DEX 200 | BEQ @SETDCB ; 1: SetDCB 201 | DEX 202 | BEQ @NEWLINE ; 2: SetNewLine 203 | DEX 204 | BEQ @IRQ ; 3: ServiceInterrupt 205 | DEX 206 | BEQ @EJECT ; 4: Eject 207 | 208 | @NEWLINE: LDA #ERR_BADCTL 209 | SEC 210 | @RESET: 211 | @SETDCB: 212 | @EJECT: LDA #NO_ERR ; only return OK 213 | CLC 214 | RTS 215 | 216 | @IRQ: LDA #ERR_NOINT ; interrupts not supported 217 | SEC 218 | RTS 219 | 220 | 221 | ; Get control/status list pointer and code 222 | ; 223 | GETCSLIST: LDY #2 224 | LDA (SMPARAMLIST),Y 225 | STA SMCMDLIST ; get buffer pointer 226 | INY 227 | LDA (SMPARAMLIST),Y 228 | STA SMCMDLIST+1 229 | INY 230 | LDA (SMPARAMLIST),Y 231 | STA SMCSCODE ; get status/control code 232 | RTS 233 | 234 | 235 | ; Smartport Read Block command 236 | ; 237 | ; reads a 512-byte block using the ProDOS function 238 | ; 239 | SMREADBLOCK: 240 | JSR TRANSLATE 241 | BCC @READ 242 | RTS 243 | 244 | @READ: LDX SLOT16 245 | LDY SLOT 246 | JMP READ ; call ProDOS read 247 | 248 | 249 | 250 | ; Smartport Write Block command 251 | ; 252 | ; writes a 512-byte block using the ProDOS function 253 | ; 254 | SMWRITEBLOCK: 255 | JSR TRANSLATE 256 | BCC @WRITE 257 | RTS 258 | 259 | @WRITE: LDX SLOT16 260 | LDY SLOT 261 | JMP WRITE ; call ProDOS write 262 | 263 | 264 | ; Translates the Smartport unit number to a ProDOS device 265 | ; and prepares the block number 266 | ; 267 | ; Unit 0: entire chain, not supported 268 | ; Unit 1: this slot, drive 0 269 | ; Unit 2: this slot, drive 1 270 | ; Unit 3: phantom slot, drive 0 271 | ; Unit 4: phantom slot, drive 1 272 | ; 273 | TRANSLATE: LDA DRVNUM,Y 274 | BEQ @BADUNIT ; not supportd for unit 0 275 | CMP #1 276 | BEQ @UNIT1 277 | CMP #2 278 | BEQ @UNIT2 279 | CMP #3 280 | BEQ @UNIT3 281 | CMP #4 282 | BEQ @UNIT4 283 | BRA @BADUNIT ; only 4 partitions are supported 284 | 285 | @UNIT1: LDA SLOT16 ; this slot 286 | BRA @STORE 287 | @UNIT2: LDA SLOT16 288 | ORA #$80 ; drive 1 289 | BRA @STORE 290 | @UNIT3: LDA SLOT16 291 | DEC A ; phantom slot 292 | BRA @STORE 293 | @UNIT4: LDA SLOT16 294 | DEC A ; phantom slot 295 | ORA #$80 ; drive 1 296 | 297 | @STORE: STA DSNUMBER ; store in ProDOS variable 298 | 299 | LDY #2 ; get buffer pointer 300 | LDA (SMPARAMLIST),Y 301 | STA BUFFER 302 | INY 303 | LDA (SMPARAMLIST),Y 304 | STA BUFFER+1 305 | 306 | INY ; get block number 307 | LDA (SMPARAMLIST),Y 308 | STA BLOCKNUM 309 | INY 310 | LDA (SMPARAMLIST),Y 311 | STA BLOCKNUM+1 312 | INY 313 | LDA (SMPARAMLIST),Y 314 | BNE @BADBLOCK ; bit 23-16 need to be 0 315 | 316 | CLC 317 | RTS 318 | 319 | @BADUNIT: LDA #ERR_BADUNIT 320 | SEC 321 | RTS 322 | 323 | @BADBLOCK: LDA #ERR_BADBLOCK 324 | SEC 325 | RTS 326 | 327 | 328 | ; Smartport Format command 329 | ; 330 | ; supported, but doesn't do anything 331 | ; unit number must not be 0 332 | ; 333 | SMFORMAT: LDA DRVNUM,Y 334 | BEQ @ERROR 335 | LDA #NO_ERR 336 | CLC 337 | RTS 338 | 339 | @ERROR: LDA #ERR_BADUNIT 340 | SEC 341 | RTS 342 | 343 | 344 | ; Smartport Init comand 345 | ; 346 | ; supported, but doesn't do anything 347 | ; unit number must be 0 348 | ; 349 | SMINIT: LDA DRVNUM,Y 350 | CLC 351 | BEQ @END ; error if not 0 352 | LDA #ERR_BADUNIT 353 | SEC 354 | @END: RTS 355 | 356 | 357 | ; Smartport Open and Close commands 358 | ; 359 | ; supported for character devices, only 360 | ; 361 | SMOPEN: 362 | SMCLOSE: LDA #ERR_BADCMD 363 | SEC 364 | RTS 365 | 366 | 367 | ; Smartport Read Character and Write Character 368 | ; 369 | ; only 512-byte block operations are supported 370 | ; 371 | SMREADCHAR: 372 | SMWRITECHAR: 373 | LDA #ERR_IOERR 374 | SEC 375 | RTS 376 | 377 | 378 | ; Required parameter counts for the commands 379 | REQPARAMCOUNT: 380 | .byt 3 ; 0 = status 381 | .byt 3 ; 1 = read block 382 | .byt 3 ; 2 = write block 383 | .byt 1 ; 3 = format 384 | .byt 3 ; 4 = control 385 | .byt 1 ; 5 = init 386 | .byt 1 ; 6 = open 387 | .byt 1 ; 7 = close 388 | .byt 4 ; 8 = read char 389 | .byt 4 ; 9 = write char 390 | 391 | ; Command jump table 392 | SPDISPATCH: 393 | .word SMSTATUS 394 | .word SMREADBLOCK 395 | .word SMWRITEBLOCK 396 | .word SMFORMAT 397 | .word SMCONTROL 398 | .word SMINIT 399 | .word SMOPEN 400 | .word SMCLOSE 401 | .word SMREADCHAR 402 | .word SMWRITECHAR 403 | 404 | ; Status 00 command data 405 | STATUS00DATA: 406 | .byt $40 ; no interrupts 407 | .word $0000 ; unknown vendor 408 | .word SMDRIVERVER ; driver version 409 | .byt $00, $00 ; reserved 410 | .assert(*-STATUS00DATA)=7, error, "STATUS00DATA must be 7 bytes long" 411 | 412 | ; Status 3 command data 413 | STATUS3DATA: 414 | .byt 16, "APPLE][SD " ; ID length and string, padded 415 | .byt $02 ; hard disk 416 | .byt $00 ; removable hard disk 417 | .word SMDRIVERVER ; driver version 418 | .assert (*-STATUS3DATA)=21, error, "STATUS3DATA must be 21 bytes long" 419 | -------------------------------------------------------------------------------- /Hardware/PCB-POOL Standard.dru: -------------------------------------------------------------------------------- 1 | description[de] = EAGLE Design Rules Prototypen für PCB-POOL(R)\n

\nWir haben in diesem DRU File alle notwendigen Design Einstellungen vorgenommen, damit Sie Ihre Leiterplatte \ngemaess unseren Mindestanforderungen im Standard bestellen koennen. Die Optionen Shapes und Misc sind dabei nicht relevant.\nDer minimale und maximale Wert für Roundness Shapes kann frei gewählt werden.\nBitte beachten Sie, daß die Mindesteinstellungen nicht geaendert werden, da ansonsten keine Gewaehrleistung für eine \nfehlerfreie Produktion übernommen werden kann.
\nAbzudeckende Vias koennen in Masks (unter Limit) eingestellt werden.\n

Ihr Beta LAYOUT Team\n

\nEAGLE Design Rules Prototypes to use with PCB-POOL(R)\n

\nThe design rules in this DRU file have been set to cover our minimum standard requirements, the options Shapes and Misc are not\nrelevant. Values for Roundness (Shapes) can be chosen freely. Please do not change these minimum\nrequirements to avoid problems during production.
\nCovered vias can be set in Masks (Limit).\n\n

Your Beta LAYOUT Team 2 | layerSetup = (1*16) 3 | mtCopper = 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 0.035mm 4 | mtIsolate = 1.5mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 0.15mm 0.2mm 5 | mdWireWire = 0.15mm 6 | mdWirePad = 0.15mm 7 | mdWireVia = 0.15mm 8 | mdPadPad = 0.15mm 9 | mdPadVia = 0.15mm 10 | mdViaVia = 0.15mm 11 | mdSmdPad = 0.15mm 12 | mdSmdVia = 0.15mm 13 | mdSmdSmd = 0.15mm 14 | mdViaViaSameLayer = 0.2mm 15 | mnLayersViaInSmd = 2 16 | mdCopperDimension = 0.3mm 17 | mdDrill = 0.2mm 18 | mdSmdStop = 0mil 19 | msWidth = 0.15mm 20 | msDrill = 0.3mm 21 | msMicroVia = 25mm 22 | msBlindViaRatio = 0.500000 23 | rvPadTop = 0.000000 24 | rvPadInner = 0.000000 25 | rvPadBottom = 0.000000 26 | rvViaOuter = 0.000000 27 | rvViaInner = 0.000000 28 | rvMicroViaOuter = 0.000000 29 | rvMicroViaInner = 0.000000 30 | rlMinPadTop = 0.2mm 31 | rlMaxPadTop = 2.5mm 32 | rlMinPadInner = 0.2mm 33 | rlMaxPadInner = 2.5mm 34 | rlMinPadBottom = 0.2mm 35 | rlMaxPadBottom = 2.5mm 36 | rlMinViaOuter = 0.15mm 37 | rlMaxViaOuter = 2.5mm 38 | rlMinViaInner = 0.2mm 39 | rlMaxViaInner = 2.5mm 40 | rlMinMicroViaOuter = 2.5mm 41 | rlMaxMicroViaOuter = 25mm 42 | rlMinMicroViaInner = 2.5mm 43 | rlMaxMicroViaInner = 25mm 44 | psTop = -1 45 | psBottom = -1 46 | psFirst = -1 47 | psElongationLong = 100 48 | psElongationOffset = 100 49 | mvStopFrame = 0.000000 50 | mvCreamFrame = 0.000000 51 | mlMinStopFrame = 0.075mm 52 | mlMaxStopFrame = 0.2mm 53 | mlMinCreamFrame = 0mil 54 | mlMaxCreamFrame = 0.2mm 55 | mlViaStopLimit = 0mil 56 | srRoundness = 0.000000 57 | srMinRoundness = 0mil 58 | srMaxRoundness = 0mil 59 | slThermalIsolate = 0.2mm 60 | slThermalsForVias = 0 61 | dpMaxLengthDifference = 10mm 62 | dpGapFactor = 2.500000 63 | checkGrid = 0 64 | checkAngle = 0 65 | checkFont = 1 66 | checkRestrict = 1 67 | useDiameter = 13 68 | maxErrors = 50 69 | -------------------------------------------------------------------------------- /Hardware/SD_A2.gpi: -------------------------------------------------------------------------------- 1 | Generated by EAGLE CAM Processor 7.7.0 2 | 3 | Photoplotter Info File: //LUDWIG-FS/Vertrieb/TEMP/RZF/AppleIISd/SD_A2.gpi 4 | 5 | Date : 18.07.2017 10:31 6 | Plotfile : //LUDWIG-FS/Vertrieb/TEMP/RZF/AppleIISd/SD_A2.plc 7 | Apertures : generated: 8 | Device : Gerber RS-274-X photoplotter, coordinate format 2.5 inch 9 | 10 | Parameter settings: 11 | 12 | Emulate Apertures : no 13 | Tolerance Draw + : 0.00 % 14 | Tolerance Draw - : 0.00 % 15 | Tolerance Flash + : 0.00 % 16 | Tolerance Flash - : 0.00 % 17 | Rotate : no 18 | Mirror : no 19 | Optimize : yes 20 | Auto fit : yes 21 | OffsetX : 0inch 22 | OffsetY : 0inch 23 | 24 | Plotfile Info: 25 | 26 | Coordinate Format : 2.5 27 | Coordinate Units : Inch 28 | Data Mode : Absolute 29 | Zero Suppression : None 30 | End Of Block : * 31 | 32 | Apertures used: 33 | 34 | Code Shape Size used 35 | 36 | D10 draw 0.0040inch 398 37 | D11 draw 0.0060inch 196 38 | D12 draw 0.0050inch 90 39 | D13 rectangle 0.0400inch x 0.0750inch 1 40 | D14 rectangle 0.0700inch x 0.0150inch 1 41 | D15 rectangle 0.0500inch x 0.0100inch 1 42 | D16 rectangle 0.0300inch x 0.0100inch 1 43 | D17 square 0.0100inch 1 44 | D18 rectangle 0.0100inch x 0.0050inch 2 45 | D19 square 0.0050inch 8 46 | D20 draw 0.0020inch 4 47 | D21 rectangle 0.0350inch x 0.0500inch 3 48 | D22 draw 0.0070inch 37 49 | D23 rectangle 0.1000inch x 0.0100inch 1 50 | D24 draw 0.0030inch 10 51 | 52 | -------------------------------------------------------------------------------- /Hardware/TagConnect.lbr: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | >VALUE 91 | >NAME 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | >VALUE 109 | >NAME 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | >VALUE 131 | >NAME 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | >VALUE 145 | >NAME 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | >VALUE 161 | >NAME 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | >VALUE 185 | >NAME 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | Tag-Connect In Circuit Programming & Debug Cable 10 Pin 201 | http://www.tag-connect.com 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | Tag-Connect In Circuit Programming & Debug Cable 6 Pin 244 | http://www.tag-connect.com 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | -------------------------------------------------------------------------------- /Hardware/con-sd-attend2.lbr: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | >NAME 132 | >VALUE 133 | /CS 134 | Din 135 | GND 136 | VCC 137 | CLK 138 | GND 139 | Dout 140 | NC 141 | NC 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 104H-TDA0-R 173 | SD-CARD-SLOT 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | -------------------------------------------------------------------------------- /Hardware/lm1117.lbr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freitz85/AppleIISd/b13ed9077f54387077b36edc959048bec4b9f689/Hardware/lm1117.lbr -------------------------------------------------------------------------------- /Images/AddessDecoder_Test.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freitz85/AppleIISd/b13ed9077f54387077b36edc959048bec4b9f689/Images/AddessDecoder_Test.JPG -------------------------------------------------------------------------------- /Images/AppleIISd_Test.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freitz85/AppleIISd/b13ed9077f54387077b36edc959048bec4b9f689/Images/AppleIISd_Test.JPG -------------------------------------------------------------------------------- /Images/Bus1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freitz85/AppleIISd/b13ed9077f54387077b36edc959048bec4b9f689/Images/Bus1.gif -------------------------------------------------------------------------------- /Images/Bus2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freitz85/AppleIISd/b13ed9077f54387077b36edc959048bec4b9f689/Images/Bus2.gif -------------------------------------------------------------------------------- /Images/Card Front SMD.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freitz85/AppleIISd/b13ed9077f54387077b36edc959048bec4b9f689/Images/Card Front SMD.jpg -------------------------------------------------------------------------------- /Images/Card Front.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freitz85/AppleIISd/b13ed9077f54387077b36edc959048bec4b9f689/Images/Card Front.jpg -------------------------------------------------------------------------------- /Images/Spi1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freitz85/AppleIISd/b13ed9077f54387077b36edc959048bec4b9f689/Images/Spi1.png -------------------------------------------------------------------------------- /Images/Spi2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/freitz85/AppleIISd/b13ed9077f54387077b36edc959048bec4b9f689/Images/Spi2.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AppleIISd 2 | SD card based ProFile replacement for enhanced Apple IIe and IIgs computers 3 | 4 | The **AppleIISd** is a SD card based replaced for the ProFile harddrive. In contrast to other SD card based devices, this card does not replace a Disk II drive. Data is saved directly onto the SD card, not via images on a FAT system, like on other cards. The SD card is accessable with [CiderPress](http://a2ciderpress.com/). 5 | 6 | A Xilinx CPLD is used as a SPI controller and translates, together with the ROM driver, SD card data to/from the Apple IIe. The VHDL source is based on [SPI65/B](http://www.6502.org/users/andre/spi65b) by André Fachat. 7 | 8 | The assembler sources are written for CC65. The [schematics](Binary/AppleIISd.pdf) are available as PDF. 9 | 10 | ## Features 11 | * works with ProDOS and GS/OS 12 | * up to 128MB storage space (4x 65535 blocks) 13 | * ProDOS and Smartport driver in ROM 14 | * Firmware update from ProDOS 15 | * Auto boot 16 | * Access LED 17 | * Card detect and write protect sensing 18 | * Skip boot when Open-Apple key is pressed 19 | 20 | ## Requirements 21 | The AppleIISd requires an enhanced IIe or IIgs computer. The ROM code uses some 65c02 opcodes and will therefore not work on a II, II+ or unenhanced IIe. It has been tested in the following combinations: 22 | * Apple IIgs Rom 01, GS/OS 6.0.4 23 | * Apple IIgs Rom 01, Prodos 2.4.1 24 | * Apple IIgs Rom 01, Prodos 1.9 25 | * Apple IIe enhanced, 128k, Prodos 2.4.1 26 | * Apple IIe enhanced, 128k, Prodos 1.9 27 | * Apple IIe enhanced, 64k, Prodos 1.9 28 | 29 | ## Binary distribution 30 | The following files in [Binary/](Binary) have been provided to eliminate the need to compile assembler or VHDL sources. 31 | 32 | | File | Purpose | 33 | | ---- | ------- | 34 | | AppleIISd_xx44.jed | CPLD bitfiles for PC44 and VQ44 formfactors | 35 | | AppleIISd.bin | 2k Firmware binary for EPROM | 36 | | AppleIISd.hex | Same as above in INTEL-HEX format | 37 | | AppleIISd.bom.txt | BOM for the board | 38 | | AppleIISd.pdf | Schematic and layout | 39 | | Flasher.bin | Flasher program ProDOS binary | 40 | | Flasher.dsk | Complete ProDOS disk image with Flasher.bin and AppleIISd.bin | 41 | | Gerber_Vx.x.zip | Gerber files for different hw revisions | 42 | 43 | ## Smartport drive remapping 44 | The AppleIISd features Smartport drivers in ROM to provide more than two drives in both GS/OS and ProDOS. 45 | 46 | As ProDOS supports only two drives per slot, additional drives on a Smartport device are mapped to 'phantom slots'. Version prior to version 2 supported only the remapping of drives when the card was in slot 5. Starting with version 2, the remapping seems to work on all slots. The following list shows the assignments as slot/drive, when no other devices are attached: 47 | 48 | * Slot 7: 7/1, 7/2, 4/1, 4/2 49 | * Slot 6: 6/1, 6/2, 4/1, 4/1 50 | * Slot 5: 5/1, 5/2, 2/1, 2/1 51 | * Slot 4: 4/1, 4/2, 1/1, 1/2 52 | * Slot 3: 80 col HW, not usable 53 | * Slot 2: 2/1, 2/2, 4/1, 4/2 54 | * Slot 1: 1/1, 1/2, 4/1, 4/2 55 | 56 | When more devices are connected, things get a little confusing ;-) 57 | 58 | ## Building the sources 59 | Be sure to have the newest version of CC65 (V2.16) and some kind of Make instaled, then type one of the following comands: 60 | ``` 61 | make # generate binaries 62 | make OPTIONS=mapfile,listing # generate mapfile and listing, too 63 | make clean # delete binaries 64 | ``` 65 | Alternatively use the VisualStudio solution. 66 | 67 | ## Timing 68 | The clock of the SPI bus *SCK* may be derived from either *Phi0* or the *7M* clock. Additionally, the divisor may be 2 to 8. 69 | 70 | The following measurements were taken with the divisor set to 2, resulting in *fSCK* of 500kHz and 3.5MHz. Reading of a byte requires that a dummy byte is sent on the bus, before the answer can be read. Therefore the measurement is the time between sending the byte and receiving the answer. The measurement for reading of a whole 512 byte block includes the SD card commands to do so. 71 | 72 | | Clock | Byte | Block | Image | 73 | | -----: | -----: | -----: | ------------------------------------------------: | 74 | | *Phi0* | 17.7µs | 28.8ms | [Byte](Images/Bus1.gif), [Block](Images/Spi1.png) | 75 | | *7M* | 3.9µs | 15ms | [Byte](Images/Bus2.gif), [Block](Images/Spi2.png) | 76 | 77 | This shows that the required to read a single byte can be reduced significantly by increasing *fSCK* (as one might have guessed). Reading at 500kHz actualy requires NOPs to be inserted (or checking the TC bit in the STATUS register), while reading at 3.5MHz can be done immediately. 78 | 79 | The time for reading a 512 byte block could *only* be halved, but there are for sure opportunities for optimization in the code surrounding the reading. 80 | 81 | ``` 82 | * single byte @ 500kHz 83 | LDA #$FF 84 | STA $C0C0 85 | NOP 86 | NOP 87 | NOP 88 | NOP 89 | NOP 90 | NOP 91 | NOP 92 | LDA $C0C0 93 | 94 | * single byte @ 3.5MHz 95 | LDA #$FF 96 | STA $C0C0 97 | LDA $C0C0 98 | ``` 99 | 100 | 101 | ## Registers 102 | The control registers of the *AppleIISd* are mapped to the usual I/O space at **$C0n0 - $C0n3**, where n is slot+8. All registers and bits are read/write, except where noted. 103 | 104 | | Address | Function | Default value | 105 | | ------- | --------------- | ------------- | 106 | | $C0n0 | DATA | - | 107 | | $C0n1 | **0:** PGMEN
**1:** -
**2:** ECE
**3:** -
**4:** FRX
**5:** BSY (R)
**6:** -
**7:** TC (R) | 0
0
0
0
0
0
0
0
| 108 | | $C0n2 | unused | $00 | 109 | | $C0n3 | **0:** /SS
**1:** -
**2:** -
**3:** -
**4:** SDHC
**5:** WP (R)
**6:** CD (R)
**7:** INIT | 1
0
0
0
0
-
-
0 | 110 | 111 | **DATA** SPI data register - Is used for both input and output. When the register is written to, the controller will output the byte on the SPI bus. When it is read from, it reflects the data that was received over the SPI bus. 112 | 113 | **PGMEN** Program Enable - Enable programing of the internal firmware eeprom. Should be reset immediately after writing to the device. 114 | 115 | **ECE** External Clock Enable - This bit enables the the external clock input to the SPI controller. In the *AppleIISd*, this effectively switches the SPI clock between 500kHz (ECE = 0) and 3.5MHz (ECE = 1). 116 | 117 | **FRX** Fast Receive mode - When set to 1, fast receive mode triggers shifting upon reading or writing the SPI Data register. When set to 0, shifting is only triggered by writing the SPI data register. 118 | 119 | **BSY** Busy - This bit is 1 as long as data is shifted out on the SPI bus. *BSY* is read-only. 120 | 121 | **TC** Transfer Complete - This flag is set when the last bit has been shifted out onto the SPI bus and is cleared when *SPI data* is read. 122 | 123 | **/SS** Slave select - Write 0 to this bit to select the SD card. 124 | 125 | **SDHC** This bit is used by the initialization routine in firmware to signalize when a SDHC card was found. Do not write to manually. 126 | 127 | **WP** Write Protect - This read-only bit is 0 when writing to the card is enabled by the switch on the card. 128 | 129 | **CD** Card Detect - This read-only bit is 0 when a card is inserted. 130 | 131 | **INIT** Initialized - This bit is set to 1 when the SD card has been initialized by the firmware. Do not write manually. 132 | 133 | ## TODOs 134 | * Much more testing 135 | * Enable more than 4 volumes under GS/OS 136 | * Support for 6502 CPUs 137 | * Support for CP/M 138 | 139 | ## Known Bugs 140 | * Programs not startable from partitions 3 and 4 under ProDOS 141 | 142 | 143 | ![Front_Img_Smd](Images/Card%20Front%20SMD.jpg) 144 | ![Front_Img](Images/Card%20Front.jpg) 145 | -------------------------------------------------------------------------------- /Software/Flasher.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | {B2CF2E9D-62A7-4A68-9477-9B15A8707E78} 27 | MakeFileProj 28 | Flasher 29 | 30 | 31 | 32 | Makefile 33 | true 34 | v140 35 | 36 | 37 | Makefile 38 | false 39 | v140 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | __APPLE2__;__APPLE2ENH__;__fastcall__=__fastcall;_MSC_VER=0;__attribute__ 55 | $(PATH);C:\cc65\bin 56 | C:\cc65\include 57 | C:\cc65\lib 58 | 59 | 60 | $(MAKE_HOME)\make OPTIONS=mapfile,listing 61 | $(ProjectDir)\src 62 | $(MAKE_HOME)\make clean 63 | $(MAKE_HOME)\make OPTIONS=mapfile,listing 64 | $(SolutionDir)\ 65 | $(MAKE_HOME)\make clean 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | del /S /Q "$(ProjectDir)makefile.options 74 | $(MAKE_HOME)\make -C "$(ProjectDir)\" PROGRAM="$(ProjectDir)$(Configuration)\$(ProjectName)" 75 | rmdir /S /Q "$(ProjectDir)obj\Win32" 76 | rmdir /S /Q "$(SolutionDir)Release" 77 | del /S /Q "$(ProjectDir)makefile.options 78 | $(MAKE_HOME)\make clean -C "$(ProjectDir)\" PROGRAM="$(ProjectDir)$(Configuration)\$(ProjectName)" 79 | $(MAKE_HOME)\make -C "$(ProjectDir)\" PROGRAM="$(ProjectDir)$(Configuration)\$(ProjectName)" 80 | rmdir /S /Q "$(ProjectDir)obj\Win32" 81 | rmdir /S /Q "$(SolutionDir)Release" 82 | 83 | del /S /Q "$(ProjectDir)makefile.options 84 | $(MAKE_HOME)\make clean -C "$(ProjectDir)\" PROGRAM="$(ProjectDir)$(Configuration)\$(ProjectName)" 85 | rmdir /S /Q "$(ProjectDir)obj\Win32" 86 | rmdir /S /Q "$(SolutionDir)Release" 87 | $(PATH);C:\cc65\bin 88 | $(VC_IncludePath);C:\cc65\include 89 | 90 | C:\cc65\lib 91 | 92 | 93 | $(SolutionDir)$\ 94 | 95 | 96 | 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /Software/Flasher.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Software/apple2enh-system.cfg: -------------------------------------------------------------------------------- 1 | # Configuration for ProDOS 8 system programs (allowing for 3KB in LC) 2 | 3 | SYMBOLS { 4 | __EXEHDR__: type = import; 5 | __FILETYPE__: type = weak, value = $00FF; # ProDOS file type 6 | __STACKSIZE__: type = weak, value = $0800; # 2k stack 7 | __LCADDR__: type = weak, value = $D400; # Behind quit code 8 | __LCSIZE__: type = weak, value = $0C00; # Rest of bank two 9 | } 10 | MEMORY { 11 | ZP: file = "", define = yes, start = $0080, size = $001A; 12 | HEADER: file = %O, start = $2000 - $003A, size = $003A; 13 | MAIN: file = %O, define = yes, start = $2000, size = $BF00 - $2000; 14 | BSS: file = "", start = __ONCE_RUN__, size = $BF00 - __STACKSIZE__ - __ONCE_RUN__; 15 | LC: file = "", define = yes, start = __LCADDR__, size = __LCSIZE__; 16 | } 17 | SEGMENTS { 18 | ZEROPAGE: load = ZP, type = zp; 19 | EXEHDR: load = HEADER, type = ro, optional = yes; 20 | STARTUP: load = MAIN, type = ro; 21 | LOWCODE: load = MAIN, type = ro, optional = yes; 22 | CODE: load = MAIN, type = ro; 23 | RODATA: load = MAIN, type = ro; 24 | DATA: load = MAIN, type = rw; 25 | INIT: load = MAIN, type = rw; 26 | ONCE: load = MAIN, type = ro, define = yes; 27 | LC: load = MAIN, run = LC, type = ro, optional = yes; 28 | BSS: load = BSS, type = bss, define = yes; 29 | } 30 | FEATURES { 31 | CONDES: type = constructor, 32 | label = __CONSTRUCTOR_TABLE__, 33 | count = __CONSTRUCTOR_COUNT__, 34 | segment = ONCE; 35 | CONDES: type = destructor, 36 | label = __DESTRUCTOR_TABLE__, 37 | count = __DESTRUCTOR_COUNT__, 38 | segment = RODATA; 39 | CONDES: type = interruptor, 40 | label = __INTERRUPTOR_TABLE__, 41 | count = __INTERRUPTOR_COUNT__, 42 | segment = RODATA, 43 | import = __CALLIRQ__; 44 | } 45 | -------------------------------------------------------------------------------- /Software/make_image.bat: -------------------------------------------------------------------------------- 1 | make clean 2 | make 3 | java -jar ..\Binary\AppleCommander-ac-1.5.0.jar -d ..\Binary\Flasher.dsk flasher 4 | java -jar ..\Binary\AppleCommander-ac-1.5.0.jar -as ..\Binary\Flasher.dsk flasher < Flasher.bin 5 | copy Flasher.bin ..\Binary -------------------------------------------------------------------------------- /Software/make_image.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | make clean 4 | make 5 | java -jar ../Binary/AppleCommander-ac-1.5.0.jar -d ../Binary/Flasher.dsk flasher 6 | java -jar ../Binary/AppleCommander-ac-1.5.0.jar -as ../Binary/Flasher.dsk flasher < Flasher.bin 7 | cp Flasher.bin ../Binary/ 8 | -------------------------------------------------------------------------------- /Software/makefile: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | ### Generic Makefile for cc65 projects - full version with abstract options ### 3 | ### V1.3.0(w) 2010 - 2013 Oliver Schmidt & Patryk "Silver Dream !" ?ogiewa ### 4 | ############################################################################### 5 | 6 | ############################################################################### 7 | ### In order to override defaults - values can be assigned to the variables ### 8 | ############################################################################### 9 | 10 | # Space or comma separated list of cc65 supported target platforms to build for. 11 | # Default: c64 (lowercase!) 12 | TARGETS := apple2enh 13 | 14 | # Name of the final, single-file executable. 15 | # Default: name of the current dir with target name appended 16 | PROGRAM := Flasher 17 | 18 | # Path(s) to additional libraries required for linking the program 19 | # Use only if you don't want to place copies of the libraries in SRCDIR 20 | # Default: none 21 | LIBS := 22 | 23 | # Custom linker configuration file 24 | # Use only if you don't want to place it in SRCDIR 25 | # Default: none 26 | CONFIG := apple2enh-system.cfg 27 | 28 | # Additional C compiler flags and options. 29 | # Default: none 30 | CFLAGS = 31 | 32 | # Additional assembler flags and options. 33 | # Default: none 34 | ASFLAGS = 35 | 36 | # Additional linker flags and options. 37 | # Default: none 38 | LDFLAGS = 39 | 40 | # Path to the directory containing C and ASM sources. 41 | # Default: src 42 | SRCDIR := 43 | 44 | # Path to the directory where object files are to be stored (inside respective target subdirectories). 45 | # Default: obj 46 | OBJDIR := 47 | 48 | # Command used to run the emulator. 49 | # Default: depending on target platform. For default (c64) target: x64 -kernal kernal -VICIIdsize -autoload 50 | EMUCMD := 51 | 52 | # Optional commands used before starting the emulation process, and after finishing it. 53 | # Default: none 54 | # Examples 55 | #PREEMUCMD := osascript -e "tell application \"System Events\" to set isRunning to (name of processes) contains \"X11.bin\"" -e "if isRunning is true then tell application \"X11\" to activate" 56 | #PREEMUCMD := osascript -e "tell application \"X11\" to activate" 57 | #POSTEMUCMD := osascript -e "tell application \"System Events\" to tell process \"X11\" to set visible to false" 58 | #POSTEMUCMD := osascript -e "tell application \"Terminal\" to activate" 59 | PREEMUCMD := 60 | POSTEMUCMD := 61 | 62 | # On Windows machines VICE emulators may not be available in the PATH by default. 63 | # In such case, please set the variable below to point to directory containing 64 | # VICE emulators. 65 | #VICE_HOME := "C:\Program Files\WinVICE-2.2-x86\" 66 | VICE_HOME := 67 | 68 | # Options state file name. You should not need to change this, but for those 69 | # rare cases when you feel you really need to name it differently - here you are 70 | STATEFILE := Makefile.options 71 | 72 | ################################################################################### 73 | #### DO NOT EDIT BELOW THIS LINE, UNLESS YOU REALLY KNOW WHAT YOU ARE DOING! #### 74 | ################################################################################### 75 | 76 | ################################################################################### 77 | ### Mapping abstract options to the actual compiler, assembler and linker flags ### 78 | ### Predefined compiler, assembler and linker flags, used with abstract options ### 79 | ### valid for 2.14.x. Consult the documentation of your cc65 version before use ### 80 | ################################################################################### 81 | 82 | # Compiler flags used to tell the compiler to optimise for SPEED 83 | define _optspeed_ 84 | CFLAGS += -Oris 85 | endef 86 | 87 | # Compiler flags used to tell the compiler to optimise for SIZE 88 | define _optsize_ 89 | CFLAGS += -Or 90 | endef 91 | 92 | # Compiler and assembler flags for generating listings 93 | define _listing_ 94 | CFLAGS += --listing $$(@:.o=.lst) -T 95 | ASFLAGS += --listing $$(@:.o=.lst) 96 | REMOVES += $(addsuffix .lst,$(basename $(OBJECTS))) 97 | endef 98 | 99 | # Linker flags for generating map file 100 | define _mapfile_ 101 | LDFLAGS += --mapfile $$@.map 102 | REMOVES += $(PROGRAM).map 103 | endef 104 | 105 | # Linker flags for generating VICE label file 106 | define _labelfile_ 107 | LDFLAGS += -Ln $$@.lbl 108 | REMOVES += $(PROGRAM).lbl 109 | endef 110 | 111 | # Linker flags for generating a debug file 112 | define _debugfile_ 113 | LDFLAGS += -Wl --dbgfile,$$@.dbg 114 | REMOVES += $(PROGRAM).dbg 115 | endef 116 | 117 | ############################################################################### 118 | ### Defaults to be used if nothing defined in the editable sections above ### 119 | ############################################################################### 120 | 121 | # Presume the C64 target like the cl65 compile & link utility does. 122 | # Set TARGETS to override. 123 | ifeq ($(TARGETS),) 124 | TARGETS := c64 125 | endif 126 | 127 | # Presume we're in a project directory so name the program like the current 128 | # directory. Set PROGRAM to override. 129 | ifeq ($(PROGRAM),) 130 | PROGRAM := $(notdir $(CURDIR)) 131 | endif 132 | 133 | # Presume the C and asm source files to be located in the subdirectory 'src'. 134 | # Set SRCDIR to override. 135 | ifeq ($(SRCDIR),) 136 | SRCDIR := src 137 | endif 138 | 139 | # Presume the object and dependency files to be located in the subdirectory 140 | # 'obj' (which will be created). Set OBJDIR to override. 141 | ifeq ($(OBJDIR),) 142 | OBJDIR := obj 143 | endif 144 | TARGETOBJDIR := $(OBJDIR) 145 | 146 | # On Windows it is mandatory to have CC65_HOME set. So do not unnecessarily 147 | # rely on cl65 being added to the PATH in this scenario. 148 | ifdef CC65_HOME 149 | CC := $(CC65_HOME)/bin/cl65 150 | else 151 | CC := cl65 152 | endif 153 | 154 | # Default emulator commands and options for particular targets. 155 | # Set EMUCMD to override. 156 | c64_EMUCMD := $(VICE_HOME)x64 -kernal kernal -VICIIdsize -autoload 157 | c128_EMUCMD := $(VICE_HOME)x128 -kernal kernal -VICIIdsize -autoload 158 | vic20_EMUCMD := $(VICE_HOME)xvic -kernal kernal -VICdsize -autoload 159 | pet_EMUCMD := $(VICE_HOME)xpet -Crtcdsize -autoload 160 | plus4_EMUCMD := $(VICE_HOME)xplus4 -TEDdsize -autoload 161 | # So far there is no x16 emulator in VICE (why??) so we have to use xplus4 with -memsize option 162 | c16_EMUCMD := $(VICE_HOME)xplus4 -ramsize 16 -TEDdsize -autoload 163 | cbm510_EMUCMD := $(VICE_HOME)xcbm2 -model 510 -VICIIdsize -autoload 164 | cbm610_EMUCMD := $(VICE_HOME)xcbm2 -model 610 -Crtcdsize -autoload 165 | atari_EMUCMD := atari800 -windowed -xl -pal -nopatchall -run 166 | 167 | ifeq ($(EMUCMD),) 168 | EMUCMD = $($(CC65TARGET)_EMUCMD) 169 | endif 170 | 171 | ############################################################################### 172 | ### The magic begins ### 173 | ############################################################################### 174 | 175 | # The "Native Win32" GNU Make contains quite some workarounds to get along with 176 | # cmd.exe as shell. However it does not provide means to determine that it does 177 | # actually activate those workarounds. Especially $(SHELL) does NOT contain the 178 | # value 'cmd.exe'. So the usual way to determine if cmd.exe is being used is to 179 | # execute the command 'echo' without any parameters. Only cmd.exe will return a 180 | # non-empty string - saying 'ECHO is on/off'. 181 | # 182 | # Many "Native Win32" programs accept '/' as directory delimiter just fine. How- 183 | # ever the internal commands of cmd.exe generally require '\' to be used. 184 | # 185 | # cmd.exe has an internal command 'mkdir' that doesn't understand nor require a 186 | # '-p' to create parent directories as needed. 187 | # 188 | # cmd.exe has an internal command 'del' that reports a syntax error if executed 189 | # without any file so make sure to call it only if there's an actual argument. 190 | ifeq ($(shell echo),) 191 | MKDIR = mkdir -p $1 192 | RMDIR = rmdir $1 193 | RMFILES = $(RM) $1 194 | else 195 | MKDIR = mkdir $(subst /,\,$1) 196 | RMDIR = rmdir $(subst /,\,$1) 197 | RMFILES = $(if $1,del /f $(subst /,\,$1)) 198 | endif 199 | COMMA := , 200 | SPACE := $(N/A) $(N/A) 201 | define NEWLINE 202 | 203 | 204 | endef 205 | # Note: Do not remove any of the two empty lines above ! 206 | 207 | TARGETLIST := $(subst $(COMMA),$(SPACE),$(TARGETS)) 208 | 209 | ifeq ($(words $(TARGETLIST)),1) 210 | 211 | # Set PROGRAM to something like 'myprog.c64'. 212 | override PROGRAM := $(PROGRAM).bin 213 | 214 | # Set SOURCES to something like 'src/foo.c src/bar.s'. 215 | # Use of assembler files with names ending differently than .s is deprecated! 216 | SOURCES := $(wildcard $(SRCDIR)/*.c) 217 | SOURCES += $(wildcard $(SRCDIR)/*.s) 218 | SOURCES += $(wildcard $(SRCDIR)/*.asm) 219 | SOURCES += $(wildcard $(SRCDIR)/*.a65) 220 | 221 | # Add to SOURCES something like 'src/c64/me.c src/c64/too.s'. 222 | # Use of assembler files with names ending differently than .s is deprecated! 223 | SOURCES += $(wildcard $(SRCDIR)/$(TARGETLIST)/*.c) 224 | SOURCES += $(wildcard $(SRCDIR)/$(TARGETLIST)/*.s) 225 | SOURCES += $(wildcard $(SRCDIR)/$(TARGETLIST)/*.asm) 226 | SOURCES += $(wildcard $(SRCDIR)/$(TARGETLIST)/*.a65) 227 | 228 | # Set OBJECTS to something like 'obj/c64/foo.o obj/c64/bar.o'. 229 | OBJECTS := $(addsuffix .o,$(basename $(addprefix $(TARGETOBJDIR)/,$(notdir $(SOURCES))))) 230 | 231 | # Set DEPENDS to something like 'obj/c64/foo.d obj/c64/bar.d'. 232 | DEPENDS := $(OBJECTS:.o=.d) 233 | 234 | # Add to LIBS something like 'src/foo.lib src/c64/bar.lib'. 235 | LIBS += $(wildcard $(SRCDIR)/*.lib) 236 | LIBS += $(wildcard $(SRCDIR)/$(TARGETLIST)/*.lib) 237 | 238 | # Add to CONFIG something like 'src/c64/bar.cfg src/foo.cfg'. 239 | CONFIG += $(wildcard $(SRCDIR)/$(TARGETLIST)/*.cfg) 240 | CONFIG += $(wildcard $(SRCDIR)/*.cfg) 241 | 242 | # Select CONFIG file to use. Target specific configs have higher priority. 243 | ifneq ($(word 2,$(CONFIG)),) 244 | CONFIG := $(firstword $(CONFIG)) 245 | $(info Using config file $(CONFIG) for linking) 246 | endif 247 | 248 | .SUFFIXES: 249 | .PHONY: all test clean zap love 250 | 251 | all: $(PROGRAM) 252 | 253 | -include $(DEPENDS) 254 | -include $(STATEFILE) 255 | 256 | # If OPTIONS are given on the command line then save them to STATEFILE 257 | # if (and only if) they have actually changed. But if OPTIONS are not 258 | # given on the command line then load them from STATEFILE. Have object 259 | # files depend on STATEFILE only if it actually exists. 260 | ifeq ($(origin OPTIONS),command line) 261 | ifneq ($(OPTIONS),$(_OPTIONS_)) 262 | ifeq ($(OPTIONS),) 263 | $(info Removing OPTIONS) 264 | $(shell $(RM) $(STATEFILE)) 265 | $(eval $(STATEFILE):) 266 | else 267 | $(info Saving OPTIONS=$(OPTIONS)) 268 | $(shell echo _OPTIONS_=$(OPTIONS) > $(STATEFILE)) 269 | endif 270 | $(eval $(OBJECTS): $(STATEFILE)) 271 | endif 272 | else 273 | ifeq ($(origin _OPTIONS_),file) 274 | $(info Using saved OPTIONS=$(_OPTIONS_)) 275 | OPTIONS = $(_OPTIONS_) 276 | $(eval $(OBJECTS): $(STATEFILE)) 277 | endif 278 | endif 279 | 280 | # Transform the abstract OPTIONS to the actual cc65 options. 281 | $(foreach o,$(subst $(COMMA),$(SPACE),$(OPTIONS)),$(eval $(_$o_))) 282 | 283 | # Strip potential variant suffix from the actual cc65 target. 284 | CC65TARGET := $(firstword $(subst .,$(SPACE),$(TARGETLIST))) 285 | 286 | # The remaining targets. 287 | $(TARGETOBJDIR): 288 | $(call MKDIR,$@) 289 | 290 | vpath %.c $(SRCDIR)/$(TARGETLIST) $(SRCDIR) 291 | 292 | $(TARGETOBJDIR)/%.o: %.c | $(TARGETOBJDIR) 293 | $(CC) -t $(CC65TARGET) -c --create-dep $(@:.o=.d) $(CFLAGS) -o $@ $< 294 | 295 | vpath %.s $(SRCDIR)/$(TARGETLIST) $(SRCDIR) 296 | 297 | $(TARGETOBJDIR)/%.o: %.s | $(TARGETOBJDIR) 298 | $(CC) -t $(CC65TARGET) -c --create-dep $(@:.o=.d) $(ASFLAGS) -o $@ $< 299 | 300 | vpath %.asm $(SRCDIR)/$(TARGETLIST) $(SRCDIR) 301 | 302 | $(TARGETOBJDIR)/%.o: %.asm | $(TARGETOBJDIR) 303 | $(CC) -t $(CC65TARGET) -c --create-dep $(@:.o=.d) $(ASFLAGS) -o $@ $< 304 | 305 | vpath %.a65 $(SRCDIR)/$(TARGETLIST) $(SRCDIR) 306 | 307 | $(TARGETOBJDIR)/%.o: %.a65 | $(TARGETOBJDIR) 308 | $(CC) -t $(CC65TARGET) -c --create-dep $(@:.o=.d) $(ASFLAGS) -o $@ $< 309 | 310 | $(PROGRAM): $(CONFIG) $(OBJECTS) $(LIBS) 311 | $(CC) -t $(CC65TARGET) $(LDFLAGS) -o $@ $(patsubst %.cfg,-C %.cfg,$^) 312 | 313 | test: $(PROGRAM) 314 | $(PREEMUCMD) 315 | $(EMUCMD) $< 316 | $(POSTEMUCMD) 317 | 318 | clean: 319 | $(call RMFILES,$(OBJECTS)) 320 | $(call RMFILES,$(DEPENDS)) 321 | $(call RMFILES,$(REMOVES)) 322 | $(call RMFILES,$(PROGRAM)) 323 | 324 | else # $(words $(TARGETLIST)),1 325 | 326 | all test clean: 327 | $(foreach t,$(TARGETLIST),$(MAKE) TARGETS=$t $@$(NEWLINE)) 328 | 329 | endif # $(words $(TARGETLIST)),1 330 | 331 | OBJDIRLIST := $(wildcard $(OBJDIR)/*) 332 | 333 | zap: 334 | $(foreach o,$(OBJDIRLIST),-$(call RMFILES,$o/*.o $o/*.d $o/*.lst)$(NEWLINE)) 335 | $(foreach o,$(OBJDIRLIST),-$(call RMDIR,$o)$(NEWLINE)) 336 | -$(call RMDIR,$(OBJDIR)) 337 | -$(call RMFILES,$(basename $(PROGRAM)).* $(STATEFILE)) 338 | 339 | love: 340 | @echo "Not war, eh?" 341 | 342 | ################################################################### 343 | ### Place your additional targets in the additional Makefiles ### 344 | ### in the same directory - their names have to end with ".mk"! ### 345 | ################################################################### 346 | -include *.mk -------------------------------------------------------------------------------- /Software/src/AppleIISd.h: -------------------------------------------------------------------------------- 1 | #ifndef APPLE_II_SD_H 2 | #define APPLE_II_SD_H 3 | 4 | typedef unsigned char uint8; 5 | typedef unsigned short uint16; 6 | typedef unsigned long uint32; 7 | typedef unsigned char boolean; 8 | 9 | #ifndef TRUE 10 | #define TRUE 1 11 | #endif 12 | #ifndef FALSE 13 | #define FALSE 0 14 | #endif 15 | 16 | #define SLOT_IO_START (volatile uint8*)0xC080 17 | #define SLOT_ROM_START (volatile uint8*)0xC000 18 | #define EXT_ROM_START (volatile uint8*)0xC800 19 | 20 | #define CFFF (volatile uint8*)0xCFFF 21 | 22 | typedef volatile struct 23 | { 24 | // data register 25 | // +0 26 | uint8 data; 27 | 28 | // status register 29 | // +1 30 | union 31 | { 32 | struct 33 | { 34 | unsigned pgmen : 1; 35 | unsigned : 1; 36 | unsigned ece : 1; 37 | unsigned : 1; 38 | unsigned frx : 1; 39 | const unsigned bsy : 1; 40 | unsigned : 1; 41 | const unsigned tc : 1; 42 | }; 43 | 44 | uint8 status; 45 | } status; 46 | 47 | // clock divisor register, unused 48 | // +2 49 | uint8 clkDiv; 50 | 51 | // slave select and card state register 52 | // +3 53 | union 54 | { 55 | struct 56 | { 57 | unsigned slaveSel : 1; 58 | unsigned : 3; 59 | unsigned sdhc : 1; 60 | const unsigned wp : 1; 61 | const unsigned card : 1; 62 | unsigned inited : 1; 63 | }; 64 | 65 | uint8 ss_card; 66 | } ss_card; 67 | } APPLE_II_SD_T; 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /Software/src/Flasher.c: -------------------------------------------------------------------------------- 1 | #include "AppleIISd.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | // Binary can't be larger than 2k 11 | #define BUFFER_SIZE 2048 12 | #define BIN_FILE_NAME "AppleIISd.bin" 13 | 14 | typedef enum 15 | { 16 | STATE_0, // pipe 17 | STATE_1, // slash 18 | STATE_2, // hyphen 19 | STATE_3, // backslash 20 | 21 | STATE_LAST // don't use 22 | } STATE_CURSOR_T; 23 | 24 | const char state_char[STATE_LAST] = { '|', '/', '-', '\\' }; 25 | static uint8 buffer[BUFFER_SIZE]; 26 | 27 | static void writeChip(const uint8* pSource, volatile uint8* pDest, uint16 length); 28 | static boolean verifyChip(const uint8* pSource, volatile uint8* pDest, uint16 length); 29 | static void printStatus(uint8 percentage); 30 | 31 | int main() 32 | { 33 | int retval = 1; 34 | FILE* pFile; 35 | char slotNum; 36 | boolean erase = FALSE; 37 | uint16 fileSize = 0; 38 | 39 | APPLE_II_SD_T* pAIISD; 40 | volatile uint8* pSlotRom = SLOT_ROM_START; 41 | volatile uint8 dummy; 42 | 43 | videomode(VIDEOMODE_40COL); 44 | clrscr(); 45 | cprintf("AppleIISd firmware flasher V1.2\r\n"); 46 | cprintf("(c) 2019-2020 Florian Reitz\r\n\r\n"); 47 | 48 | // ask for slot 49 | cursor(1); // enable blinking cursor 50 | cprintf("Slot number (1-7): "); 51 | cscanf("%c", &slotNum); 52 | slotNum -= 0x30; 53 | cursor(0); // disable blinking cursor 54 | 55 | if(slotNum == 0) 56 | { 57 | // erase device 58 | erase = TRUE; 59 | // ask for slot 60 | cursor(1); // enable blinking cursor 61 | cprintf("Erase device in slot number (1-7): "); 62 | cscanf("%c", &slotNum); 63 | slotNum -= 0x30; 64 | cursor(0); // disable blinking cursor 65 | } 66 | 67 | // check if slot is valid 68 | if((slotNum < 1) || (slotNum > 7)) 69 | { 70 | cprintf("\r\nInvalid slot number!"); 71 | cgetc(); 72 | return 1; // failure 73 | } 74 | 75 | pAIISD = (APPLE_II_SD_T*)(SLOT_IO_START + (slotNum << 4)); 76 | pSlotRom += slotNum << 8; 77 | 78 | if(erase) 79 | { 80 | fileSize = BUFFER_SIZE; 81 | memset(buffer, 0, sizeof(buffer)); 82 | } 83 | else 84 | { 85 | // open file 86 | pFile = fopen(BIN_FILE_NAME, "rb"); 87 | if(pFile) 88 | { 89 | // read buffer 90 | fileSize = fread(buffer, 1, sizeof(buffer), pFile); 91 | fclose(pFile); 92 | pFile = NULL; 93 | 94 | if(fileSize != BUFFER_SIZE) 95 | { 96 | cprintf("\r\nWrong file size: %d\r\n", fileSize); 97 | } 98 | } 99 | else 100 | { 101 | cprintf("\r\nCan't open %s file\r\n", BIN_FILE_NAME); 102 | fileSize = 0; 103 | } 104 | } 105 | 106 | if(fileSize == BUFFER_SIZE) 107 | { 108 | // enable write 109 | pAIISD->status.pgmen = 1; 110 | 111 | // write to SLOTROM 112 | cprintf("\r\n\r\nFlashing SLOTROM: "); 113 | writeChip(buffer, pSlotRom, 256); 114 | 115 | cprintf("\r\nVerifying SLOTROM: "); 116 | if(verifyChip(buffer, pSlotRom, 256)) 117 | { 118 | // write to EXT_ROM 119 | cprintf("\r\n\r\nFlashing EXTROM: "); 120 | 121 | // clear CFFF and dummy read to enable correct EXT_ROM 122 | dummy = *CFFF; 123 | dummy = *pSlotRom; 124 | 125 | writeChip(buffer + 256, EXT_ROM_START, fileSize - 256); 126 | cprintf("\r\nVerifying EXTROM: "); 127 | 128 | dummy = *CFFF; 129 | dummy = *pSlotRom; 130 | 131 | if(verifyChip(buffer + 256, EXT_ROM_START, fileSize - 256)) 132 | { 133 | cprintf("\r\n\r\nFlashing finished!\n"); 134 | retval = 0; 135 | } 136 | } 137 | 138 | // disable write 139 | pAIISD->status.pgmen = 0; 140 | } 141 | 142 | cgetc(); 143 | return retval; 144 | } 145 | 146 | static void writeChip(const uint8* pSource, volatile uint8* pDest, uint16 length) 147 | { 148 | uint32 i; 149 | volatile uint8 readData; 150 | 151 | for(i=0; i A, 88 | B => B, 89 | CLK => CLK, 90 | PHI0 => PHI0, 91 | RNW => RNW, 92 | NDEV_SEL => NDEV_SEL, 93 | NIO_SEL => NIO_SEL, 94 | NIO_STB => NIO_STB, 95 | NRESET => NRESET, 96 | DATA_EN => DATA_EN, 97 | PGM_EN => PGM_EN, 98 | NG => NG, 99 | NOE => NOE, 100 | NWE => NWE 101 | ); 102 | 103 | -- Clock process definitions 104 | CLK_process :process 105 | begin 106 | CLK <= '0'; 107 | wait for CLK_period/2; 108 | CLK <= '1'; 109 | wait for CLK_period/2; 110 | end process; 111 | 112 | PHI0_process :process(CLK) 113 | variable counter : integer range 0 to 7; 114 | begin 115 | if rising_edge(CLK) or falling_edge(CLK) then 116 | counter := counter + 1; 117 | if counter = 7 then 118 | PHI0 <= not PHI0; 119 | counter := 0; 120 | end if; 121 | end if; 122 | end process; 123 | 124 | -- Stimulus process 125 | stim_proc: process 126 | begin 127 | -- hold reset state. 128 | wait for CLK_period * 10; 129 | NRESET <= '0'; 130 | wait for CLK_period * 20; 131 | NRESET <= '1'; 132 | wait for CLK_period * 10; 133 | 134 | -- C0nX access 135 | -- NG must be '0" 136 | -- NOE must be '1' 137 | -- NWE must be '1' 138 | A <= "0000"; -- must become "000" 139 | wait until rising_edge(PHI0); 140 | NDEV_SEL <= '0'; 141 | wait until falling_edge(PHI0); 142 | assert (B="000") report "Address error" severity error; 143 | assert (NG='0') report "NG error" severity error; 144 | assert (NOE='1') report "NOE error" severity error; 145 | assert (NWE='1') report "NWE error" severity error; 146 | NDEV_SEL <= '1'; 147 | wait until rising_edge(PHI0); 148 | assert (NG='1') report "NG error" severity error; 149 | assert (NOE='1') report "NOE error" severity error; 150 | assert (NWE='1') report "NWE error" severity error; 151 | 152 | -- C0nX access, write 153 | -- NG must be '0" 154 | -- NOE must be '1' 155 | -- NWE must be '1' 156 | RNW <= '0'; 157 | A <= "0000"; -- must become "000" 158 | wait until rising_edge(PHI0); 159 | NDEV_SEL <= '0'; 160 | wait until falling_edge(PHI0); 161 | assert (B="000") report "Address error" severity error; 162 | assert (NG='0') report "NG error" severity error; 163 | assert (NOE='1') report "NOE error" severity error; 164 | assert (NWE='1') report "NWE error" severity error; 165 | NDEV_SEL <= '1'; 166 | wait until rising_edge(PHI0); 167 | 168 | -- CnXX access, select 169 | -- NG must be '0' 170 | -- NOE must be '0' 171 | -- NWE must be '1' 172 | RNW <= '1'; 173 | A <= "0100"; -- must become "000" 174 | wait until rising_edge(PHI0); 175 | NIO_SEL <= '0'; 176 | wait until falling_edge(PHI0); 177 | assert (B="000") report "Address error" severity error; 178 | assert (NG='0') report "NG error" severity error; 179 | assert (NOE='0') report "NOE error" severity error; 180 | assert (NWE='1') report "NWE error" severity error; 181 | NIO_SEL <= '1'; 182 | wait until rising_edge(PHI0); 183 | 184 | -- CnXX access, write, select 185 | -- NG must be '0' 186 | -- NOE must be '1' 187 | -- NWE must be '0' 188 | RNW <= '0'; 189 | A <= "0100"; -- must become "000" 190 | wait until rising_edge(PHI0); 191 | NIO_SEL <= '0'; 192 | wait until falling_edge(PHI0); 193 | assert (B="000") report "Address error" severity error; 194 | assert (NG='0') report "NG error" severity error; 195 | assert (NOE='1') report "NOE error" severity error; 196 | assert (NWE='0') report "NWE error" severity error; 197 | NIO_SEL <= '1'; 198 | wait until rising_edge(PHI0); 199 | 200 | -- CnXX access, write, select, no PGM_EN 201 | -- NG must be '0' 202 | -- NOE must be '1' 203 | -- NWE must be '1' 204 | RNW <= '0'; 205 | PGM_EN <= '0'; 206 | A <= "0100"; -- must become "000" 207 | wait until rising_edge(PHI0); 208 | NIO_SEL <= '0'; 209 | wait until falling_edge(PHI0); 210 | assert (B="000") report "Address error" severity error; 211 | assert (NG='0') report "NG error" severity error; 212 | assert (NOE='1') report "NOE error" severity error; 213 | assert (NWE='1') report "NWE error" severity error; 214 | NIO_SEL <= '1'; 215 | wait until rising_edge(PHI0); 216 | 217 | -- C8xx access, selected 218 | -- NG must be '0' 219 | -- NOE must be '0' 220 | -- NWE must be '1' 221 | RNW <= '1'; 222 | PGM_EN <= '1'; 223 | A <= "1000"; -- must become "001" 224 | wait until rising_edge(PHI0); 225 | NIO_STB <= '0'; 226 | wait until falling_edge(PHI0); 227 | assert (B="001") report "Address error" severity error; 228 | assert (NG='0') report "NG error" severity error; 229 | assert (NOE='0') report "NOE error" severity error; 230 | assert (NWE='1') report "NWE error" severity error; 231 | NIO_STB <= '1'; 232 | wait until rising_edge(PHI0); 233 | 234 | -- C8xx write access, selected 235 | -- NG must be '0' 236 | -- NOE must be '1' 237 | -- NWE must be '0' 238 | RNW <= '0'; 239 | wait until rising_edge(PHI0); 240 | NIO_STB <= '0'; 241 | wait until falling_edge(PHI0); 242 | assert (NG='0') report "NG error" severity error; 243 | assert (NOE='1') report "NOE error" severity error; 244 | assert (NWE='0') report "NWE error" severity error; 245 | NIO_STB <= '1'; 246 | wait until rising_edge(PHI0); 247 | 248 | -- C9xx access, selected 249 | -- NG must be '0' 250 | -- NOE must be '0' 251 | -- NWE must be '1' 252 | RNW <= '1'; 253 | A <= "1001"; -- must become "010" 254 | wait until rising_edge(PHI0); 255 | NIO_STB <= '0'; 256 | wait until falling_edge(PHI0); 257 | assert (B="010") report "Address error" severity error; 258 | assert (NG='0') report "NG error" severity error; 259 | assert (NOE='0') report "NOE error" severity error; 260 | assert (NWE='1') report "NWE error" severity error; 261 | NIO_STB <= '1'; 262 | wait until rising_edge(PHI0); 263 | 264 | -- C9xx access write, selected 265 | -- NG must be '0' 266 | -- NOE must be '1' 267 | -- NWE must be '0' 268 | RNW <= '0'; 269 | wait until rising_edge(PHI0); 270 | NIO_STB <= '0'; 271 | wait until falling_edge(PHI0); 272 | assert (NG='0') report "NG error" severity error; 273 | assert (NOE='1') report "NOE error" severity error; 274 | assert (NWE='0') report "NWE error" severity error; 275 | NIO_STB <= '1'; 276 | wait until rising_edge(PHI0); 277 | 278 | -- CPLD access 279 | -- NG must be '0' 280 | -- NOE must be '1' 281 | -- NWE must be '1' 282 | RNW <= '1'; 283 | A <= "0101"; -- must become "000" 284 | wait until rising_edge(PHI0); 285 | NDEV_SEL <= '0'; 286 | wait until falling_edge(PHI0); 287 | assert (B="000") report "Address error" severity error; 288 | assert (NG='0') report "NG error" severity error; 289 | assert (NOE='1') report "NOE error" severity error; 290 | assert (NWE='1') report "NWE error" severity error; 291 | NDEV_SEL <= '1'; 292 | wait until rising_edge(PHI0); 293 | 294 | -- CFFF access 295 | -- NG must be '1' 296 | -- NOE must be '1' 297 | -- NWE must be '1' 298 | A <= "1111"; -- must become "111" 299 | wait until rising_edge(PHI0); 300 | NIO_STB <= '0'; 301 | wait until falling_edge(PHI0); 302 | assert (B="111") report "Address error" severity error; 303 | assert (NG='1') report "NG error" severity error; 304 | assert (NOE='1') report "NOE error" severity error; 305 | assert (NWE='1') report "NWE error" severity error; 306 | NIO_STB <= '1'; 307 | wait until rising_edge(PHI0); 308 | 309 | -- C8xx access, unselected 310 | -- NG must be '1' 311 | -- NOE must be '1' 312 | -- NWE must be '1' 313 | A <= "1000"; -- must become "001" 314 | wait until rising_edge(PHI0); 315 | NIO_STB <= '0'; 316 | wait until falling_edge(PHI0); 317 | assert (B="001") report "Address error" severity error; 318 | assert (NG='1') report "NG error" severity error; 319 | assert (NOE='1') report "NOE error" severity error; 320 | assert (NWE='1') report "NWE error" severity error; 321 | NIO_STB <= '1'; 322 | wait until rising_edge(PHI0); 323 | 324 | -- C8xx access write, unselected 325 | -- NG must be '1' 326 | -- NOE must be '1' 327 | -- NWE must be '1' 328 | RNW <= '0'; 329 | A <= "1000"; -- must become "001" 330 | wait until rising_edge(PHI0); 331 | NIO_STB <= '0'; 332 | wait until falling_edge(PHI0); 333 | assert (B="001") report "Address error" severity error; 334 | assert (NG='1') report "NG error" severity error; 335 | assert (NOE='1') report "NOE error" severity error; 336 | assert (NWE='1') report "NWE error" severity error; 337 | NIO_STB <= '1'; 338 | wait until rising_edge(PHI0); 339 | 340 | wait; 341 | end process; 342 | 343 | END; 344 | -------------------------------------------------------------------------------- /VHDL/AppleIISd.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------- 2 | -- Company: 3 | -- Engineer: 4 | -- 5 | -- Create Date: 20:44:25 10/09/2017 6 | -- Design Name: 7 | -- Module Name: IO - Behavioral 8 | -- Project Name: 9 | -- Target Devices: 10 | -- Tool versions: 11 | -- Description: 12 | -- 13 | -- Dependencies: 14 | -- 15 | -- Revision: 16 | -- Revision 0.01 - File Created 17 | -- Additional Comments: 18 | -- 19 | ---------------------------------------------------------------------------------- 20 | library IEEE; 21 | use IEEE.STD_LOGIC_1164.ALL; 22 | 23 | -- Uncomment the following library declaration if using 24 | -- arithmetic functions with Signed or Unsigned values 25 | --use IEEE.NUMERIC_STD.ALL; 26 | 27 | -- Uncomment the following library declaration if instantiating 28 | -- any Xilinx primitives in this code. 29 | --library UNISIM; 30 | --use UNISIM.VComponents.all; 31 | 32 | entity AppleIISd is 33 | Port ( 34 | ADD_HIGH : in std_logic_vector(11 downto 8); 35 | ADD_LOW : in std_logic_vector(1 downto 0); 36 | B : out std_logic_vector(10 downto 8); 37 | CARD : in std_logic; 38 | DATA : inout std_logic_vector (7 downto 0); 39 | CLK : in std_logic; 40 | LED : out std_logic; 41 | NDEV_SEL : in std_logic; 42 | NG : out std_logic; 43 | NIO_SEL : in std_logic; 44 | NIO_STB : in std_logic; 45 | NOE : out std_logic; 46 | NWE : out std_logic; 47 | PHI0 : in std_logic; 48 | NRESET : in std_logic; 49 | RNW : in std_logic; 50 | MISO : in std_logic; 51 | MOSI : out std_logic; 52 | NSEL : out std_logic; 53 | SCLK : out std_logic; 54 | WP : in std_logic 55 | 56 | -- synthesis translate_off 57 | ; 58 | data_dbg : out std_logic_vector (7 downto 0); 59 | add_dbg : out std_logic_vector (1 downto 0); 60 | data_en_dbg : out std_logic 61 | -- synthesis translate_on 62 | 63 | ); 64 | end AppleIISd; 65 | 66 | architecture Behavioral of AppleIISd is 67 | 68 | signal data_in : std_logic_vector (7 downto 0); 69 | signal data_out : std_logic_vector (7 downto 0); 70 | signal addr_low_int : std_logic_vector (1 downto 0); 71 | 72 | signal data_en : std_logic; 73 | signal pgm_en : std_logic; 74 | 75 | component SpiController is 76 | Port ( 77 | data_in : in std_logic_vector (7 downto 0); 78 | data_out : out std_logic_vector (7 downto 0); 79 | is_read : in std_logic; 80 | nreset : in std_logic; 81 | addr : in std_logic_vector (1 downto 0); 82 | phi0 : in std_logic; 83 | ndev_sel : in std_logic; 84 | clk : in std_logic; 85 | miso: in std_logic; 86 | mosi : out std_logic; 87 | sclk : out std_logic; 88 | nsel : out std_logic; 89 | wp : in std_logic; 90 | card : in std_logic; 91 | led : out std_logic; 92 | pgm_en : out std_logic 93 | ); 94 | end component; 95 | 96 | component AddressDecoder 97 | Port ( 98 | A : in std_logic_vector (11 downto 8); 99 | B : out std_logic_vector (10 downto 8); 100 | CLK : in std_logic; 101 | PHI0 : in std_logic; 102 | RNW : in std_logic; 103 | NDEV_SEL : in std_logic; 104 | NIO_SEL : in std_logic; 105 | NIO_STB : in std_logic; 106 | NRESET : in std_logic; 107 | DATA_EN : out std_logic; 108 | PGM_EN : in std_logic; 109 | NG : out std_logic; 110 | NOE : out std_logic; 111 | NWE : out std_logic 112 | ); 113 | end component; 114 | 115 | 116 | begin 117 | spi: SpiController port map( 118 | data_in => data_in, 119 | data_out => data_out, 120 | is_read => RNW, 121 | nreset => NRESET, 122 | addr => addr_low_int, 123 | phi0 => PHI0, 124 | ndev_sel => NDEV_SEL, 125 | clk => CLK, 126 | miso => MISO, 127 | mosi => MOSI, 128 | sclk => SCLK, 129 | nsel => NSEL, 130 | wp => WP, 131 | card => CARD, 132 | led => LED, 133 | pgm_en => pgm_en 134 | ); 135 | 136 | addDec: AddressDecoder port map( 137 | A => ADD_HIGH, 138 | B => B, 139 | CLK => CLK, 140 | PHI0 => PHI0, 141 | RNW => RNW, 142 | NDEV_SEL => NDEV_SEL, 143 | NIO_SEL => NIO_SEL, 144 | NIO_STB => NIO_STB, 145 | NRESET => NRESET, 146 | DATA_EN => data_en, 147 | PGM_EN => pgm_en, 148 | NOE => NOE, 149 | NWE => NWE, 150 | NG => NG 151 | ); 152 | 153 | DATA <= data_out when (data_en = '1') else (others => 'Z'); -- data bus tristate 154 | 155 | -- synthesis translate_off 156 | data_dbg <= data_in; 157 | add_dbg <= addr_low_int; 158 | data_en_dbg <= data_en; 159 | -- synthesis translate_on 160 | 161 | data_latch: process(CLK) 162 | begin 163 | if falling_edge(CLK) then 164 | addr_low_int <= ADD_LOW; 165 | if (NDEV_SEL = '0') then 166 | data_in <= DATA; 167 | end if; 168 | end if; 169 | end process; 170 | 171 | end Behavioral; 172 | 173 | -------------------------------------------------------------------------------- /VHDL/AppleIISd_PC44.ucf: -------------------------------------------------------------------------------- 1 | #PACE: Start of Constraints generated by PACE 2 | 3 | #PACE: Start of PACE I/O Pin Assignments 4 | NET "ADD_HIGH<10>" LOC = "P38" ; 5 | NET "ADD_HIGH<11>" LOC = "P44" ; 6 | NET "ADD_HIGH<8>" LOC = "P36" ; 7 | NET "ADD_HIGH<9>" LOC = "P37" ; 8 | NET "ADD_LOW<0>" LOC = "P19" ; 9 | NET "ADD_LOW<1>" LOC = "P18" ; 10 | NET "B<10>" LOC = "P22" ; 11 | NET "B<8>" LOC = "P26" ; 12 | NET "B<9>" LOC = "P27" ; 13 | NET "CARD" LOC = "P33" ; 14 | NET "CLK" LOC = "P43" ; 15 | NET "DATA<0>" LOC = "P3" ; 16 | NET "DATA<1>" LOC = "P4" ; 17 | NET "DATA<2>" LOC = "P5" | BUFG = DATA_GATE ; 18 | NET "DATA<3>" LOC = "P6" | BUFG = DATA_GATE ; 19 | NET "DATA<4>" LOC = "P7" | BUFG = DATA_GATE ; 20 | NET "DATA<5>" LOC = "P9" ; 21 | NET "DATA<6>" LOC = "P11" ; 22 | NET "DATA<7>" LOC = "P13" ; 23 | NET "LED" LOC = "P29" ; 24 | NET "MISO" LOC = "P40" ; 25 | NET "MOSI" LOC = "P35" ; 26 | NET "NDEV_SEL" LOC = "P24" ; 27 | NET "NG" LOC = "P12" ; 28 | NET "NIO_SEL" LOC = "P14" ; 29 | NET "NIO_STB" LOC = "P42" ; 30 | NET "NOE" LOC = "P25" ; 31 | NET "NRESET" LOC = "P20" ; 32 | NET "NSEL" LOC = "P28" ; 33 | NET "NWE" LOC = "P2" ; 34 | NET "PHI0" LOC = "P8" ; 35 | NET "RNW" LOC = "P1" ; 36 | NET "SCLK" LOC = "P34" ; 37 | NET "WP" LOC = "P39" ; 38 | 39 | #PACE: Start of PACE Area Constraints 40 | 41 | #PACE: Start of PACE Prohibit Constraints 42 | 43 | #PACE: End of Constraints generated by PACE 44 | -------------------------------------------------------------------------------- /VHDL/AppleIISd_PC44.xise: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 |
226 | -------------------------------------------------------------------------------- /VHDL/AppleIISd_Test.vhd: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- 2 | -- Company: 3 | -- Engineer: 4 | -- 5 | -- Create Date: 00:42:59 10/10/2017 6 | -- Design Name: 7 | -- Module Name: U:/AppleIISd/VHDL/IO_Test.vhd 8 | -- Project Name: AppleIISd 9 | -- Target Device: 10 | -- Tool versions: 11 | -- Description: 12 | -- 13 | -- VHDL Test Bench Created by ISE for module: IO 14 | -- 15 | -- Dependencies: 16 | -- 17 | -- Revision: 18 | -- Revision 0.01 - File Created 19 | -- Additional Comments: 20 | -- 21 | -- Notes: 22 | -- This testbench has been automatically generated using types std_logic and 23 | -- std_logic_vector for the ports of the unit under test. Xilinx recommends 24 | -- that these types always be used for the top-level I/O of a design in order 25 | -- to guarantee that the testbench will bind correctly to the post-implementation 26 | -- simulation model. 27 | -------------------------------------------------------------------------------- 28 | LIBRARY ieee; 29 | USE ieee.std_logic_1164.ALL; 30 | 31 | -- Uncomment the following library declaration if using 32 | -- arithmetic functions with Signed or Unsigned values 33 | --USE ieee.numeric_std.ALL; 34 | 35 | ENTITY AppleIISd_Test IS 36 | END AppleIISd_Test; 37 | 38 | ARCHITECTURE behavior OF AppleIISd_Test IS 39 | 40 | -- Component Declaration for the Unit Under Test (UUT) 41 | 42 | COMPONENT AppleIISd 43 | PORT( 44 | ADD_HIGH : IN std_logic_vector(11 downto 8); 45 | ADD_LOW : IN std_logic_vector(1 downto 0); 46 | B : OUT std_logic_vector(10 downto 8); 47 | CARD : IN std_logic; 48 | DATA : INOUT std_logic_vector(7 downto 0); 49 | CLK : IN std_logic; 50 | LED : OUT std_logic; 51 | NDEV_SEL : IN std_logic; 52 | NG : OUT std_logic; 53 | NIO_SEL : IN std_logic; 54 | NIO_STB : IN std_logic; 55 | NOE : OUT std_logic; 56 | PHI0 : IN std_logic; 57 | NRESET : IN std_logic; 58 | RNW : IN std_logic; 59 | MISO : IN std_logic; 60 | MOSI : OUT std_logic; 61 | NSEL : OUT std_logic; 62 | SCLK : OUT std_logic; 63 | WP : IN std_logic; 64 | 65 | data_dbg : out std_logic_vector (7 downto 0); 66 | add_dbg : out std_logic_vector (1 downto 0); 67 | data_en_dbg : out std_logic 68 | ); 69 | END COMPONENT; 70 | 71 | 72 | --Inputs 73 | signal ADD_HIGH : std_logic_vector(11 downto 8) := (others => '0'); 74 | signal ADD_LOW : std_logic_vector(1 downto 0) := (others => 'U'); 75 | signal CARD : std_logic := '0'; 76 | signal CLK : std_logic := '0'; 77 | signal NDEV_SEL : std_logic := '1'; 78 | signal NIO_SEL : std_logic := '1'; 79 | signal NIO_STB : std_logic := '1'; 80 | signal PHI0 : std_logic := '1'; 81 | signal NRESET : std_logic := '1'; 82 | signal RNW : std_logic := '1'; 83 | signal MISO : std_logic := '1'; 84 | signal WP : std_logic := '0'; 85 | 86 | --BiDirs 87 | signal DATA : std_logic_vector(7 downto 0) := (others => 'Z'); 88 | 89 | --Outputs 90 | signal B : std_logic_vector(10 downto 8); 91 | signal LED : std_logic; 92 | signal NG : std_logic; 93 | signal NOE : std_logic; 94 | signal MOSI : std_logic; 95 | signal NSEL : std_logic; 96 | signal SCLK : std_logic; 97 | 98 | signal data_dbg : std_logic_vector (7 downto 0); 99 | signal add_dbg : std_logic_vector (1 downto 0); 100 | signal data_en_dbg : std_logic; 101 | 102 | -- Clock period definitions 103 | constant CLK_period : time := 142 ns; 104 | 105 | -- Bus timings 106 | -- worst case 107 | constant ADD_valid : time := 300 ns; -- II+ 108 | constant DATA_valid : time := 200 ns; -- II+ 109 | constant ADD_hold : time := 15 ns; -- IIgs 110 | --best case 111 | --constant ADD_valid : time := 100 ns; -- IIgs 112 | --constant DATA_valid : time := 30 ns; -- IIgs 113 | --constant ADD_hold : time := 15 ns; -- IIgs 114 | 115 | BEGIN 116 | 117 | -- Instantiate the Unit Under Test (UUT) 118 | uut: AppleIISd PORT MAP ( 119 | ADD_HIGH => ADD_HIGH, 120 | ADD_LOW => ADD_LOW, 121 | B => B, 122 | CARD => CARD, 123 | DATA => DATA, 124 | CLK => CLK, 125 | LED => LED, 126 | NDEV_SEL => NDEV_SEL, 127 | NG => NG, 128 | NIO_SEL => NIO_SEL, 129 | NIO_STB => NIO_STB, 130 | NOE => NOE, 131 | PHI0 => PHI0, 132 | NRESET => NRESET, 133 | RNW => RNW, 134 | MISO => MISO, 135 | MOSI => MOSI, 136 | NSEL => NSEL, 137 | SCLK => SCLK, 138 | WP => WP, 139 | 140 | data_dbg => data_dbg, 141 | add_dbg => add_dbg, 142 | data_en_dbg => data_en_dbg 143 | ); 144 | 145 | -- Clock process definitions 146 | CLK_process :process 147 | begin 148 | CLK <= '0'; 149 | wait for CLK_period/2; 150 | CLK <= '1'; 151 | wait for CLK_period/2; 152 | end process; 153 | 154 | PHI0_process :process(CLK) 155 | variable counter : integer range 0 to 7; 156 | begin 157 | if rising_edge(CLK) or falling_edge(CLK) then 158 | counter := counter + 1; 159 | if counter = 7 then 160 | PHI0 <= not PHI0; 161 | counter := 0; 162 | end if; 163 | end if; 164 | end process; 165 | 166 | 167 | -- Stimulus process 168 | stim_proc: process 169 | begin 170 | -- hold reset state. 171 | wait for CLK_period * 10; 172 | NRESET <= '0'; 173 | wait for CLK_period * 20; 174 | NRESET <= '1'; 175 | wait for CLK_period * 10; 176 | DATA <= (others => 'Z'); 177 | ADD_LOW <= (others => 'U'); 178 | 179 | -- read reg 3 180 | wait until falling_edge(PHI0); 181 | wait for ADD_valid; 182 | ADD_LOW <= (others => '1'); 183 | RNW <= '1'; 184 | DATA <= (others => 'U'); 185 | wait until rising_edge(PHI0); 186 | NDEV_SEL <= '0'; 187 | DATA <= (others => 'Z'); 188 | wait until falling_edge(PHI0); 189 | NDEV_SEL <= '1'; 190 | wait for ADD_hold; 191 | ADD_LOW <= (others => 'U'); 192 | 193 | -- select card 194 | wait until falling_edge(PHI0); 195 | wait for ADD_valid; 196 | ADD_LOW <= (others => '1'); 197 | RNW <= '0'; 198 | DATA <= (others => 'U'); 199 | wait until rising_edge(PHI0); 200 | NDEV_SEL <= '0'; 201 | DATA <= (others => 'Z'); 202 | wait for DATA_valid; 203 | DATA <= X"00"; 204 | wait until falling_edge(PHI0); 205 | NDEV_SEL <= '1'; 206 | wait for ADD_hold; 207 | --wait for CLK_period; 208 | ADD_LOW <= (others => 'U'); 209 | RNW <= '1'; 210 | DATA <= (others => 'Z'); 211 | 212 | -- send data 213 | wait until falling_edge(PHI0); 214 | wait for ADD_valid; 215 | ADD_LOW <= (others => '0'); 216 | RNW <= '0'; 217 | DATA <= (others => 'U'); 218 | wait until rising_edge(PHI0); 219 | NDEV_SEL <= '0'; 220 | DATA <= (others => 'Z'); 221 | wait for DATA_valid; 222 | DATA <= X"AA"; 223 | wait until falling_edge(PHI0); 224 | NDEV_SEL <= '1'; 225 | wait for ADD_hold; 226 | --wait for CLK_period; 227 | ADD_LOW <= (others => 'U'); 228 | RNW <= '1'; 229 | DATA <= (others => 'Z'); 230 | wait for 20 us; 231 | 232 | -- deselect card 233 | wait until falling_edge(PHI0); 234 | wait for ADD_valid; 235 | ADD_LOW <= (others => '1'); 236 | RNW <= '0'; 237 | DATA <= (others => 'U'); 238 | wait until rising_edge(PHI0); 239 | NDEV_SEL <= '0'; 240 | DATA <= (others => 'Z'); 241 | wait for DATA_valid; 242 | DATA <= X"01"; 243 | wait until falling_edge(PHI0); 244 | NDEV_SEL <= '1'; 245 | wait for ADD_hold; 246 | --wait for CLK_period; 247 | ADD_LOW <= (others => 'U'); 248 | RNW <= '1'; 249 | DATA <= (others => 'Z'); 250 | 251 | -- write ece 252 | wait until falling_edge(PHI0); 253 | wait for ADD_valid; 254 | ADD_LOW <= "01"; 255 | RNW <= '0'; 256 | DATA <= (others => 'U'); 257 | wait until rising_edge(PHI0); 258 | NDEV_SEL <= '0'; 259 | DATA <= (others => 'Z'); 260 | wait for DATA_valid; 261 | DATA <= x"04"; 262 | wait until falling_edge(PHI0); 263 | NDEV_SEL <= '1'; 264 | wait for ADD_hold; 265 | --wait for CLK_period; 266 | ADD_LOW <= (others => 'U'); 267 | RNW <= '1'; 268 | DATA <= (others => 'Z'); 269 | 270 | -- send data 271 | wait until falling_edge(PHI0); 272 | wait for ADD_valid; 273 | ADD_LOW <= (others => '0'); 274 | RNW <= '0'; 275 | DATA <= (others => 'U'); 276 | wait until rising_edge(PHI0); 277 | NDEV_SEL <= '0'; 278 | DATA <= (others => 'Z'); 279 | wait for DATA_valid; 280 | DATA <= X"AA"; 281 | wait until falling_edge(PHI0); 282 | NDEV_SEL <= '1'; 283 | wait for ADD_hold; 284 | --wait for CLK_period; 285 | ADD_LOW <= (others => 'U'); 286 | RNW <= '1'; 287 | DATA <= (others => 'Z'); 288 | 289 | -- read eprom low 290 | wait for 3 us; 291 | wait until falling_edge(PHI0); 292 | wait for ADD_valid; 293 | ADD_LOW <= (others => '0'); 294 | ADD_HIGH <= "0100"; -- must become "111" 295 | RNW <= '1'; 296 | DATA <= (others => 'U'); 297 | wait until rising_edge(PHI0); 298 | NIO_SEL <= '0'; 299 | DATA <= (others => 'Z'); 300 | wait until falling_edge(PHI0); 301 | NIO_SEL <= '1'; 302 | wait for ADD_hold; 303 | ADD_LOW <= (others => 'U'); 304 | ADD_HIGH <= (others => 'U'); 305 | 306 | -- read eprom high, selected 307 | wait until falling_edge(PHI0); 308 | wait for ADD_valid; 309 | ADD_LOW <= (others => '0'); 310 | ADD_HIGH <= "1001"; -- must become "001" 311 | RNW <= '1'; 312 | DATA <= (others => 'U'); 313 | wait until rising_edge(PHI0); 314 | NIO_STB <= '0'; 315 | DATA <= (others => 'Z'); 316 | wait until falling_edge(PHI0); 317 | NIO_STB <= '1'; 318 | wait for ADD_hold; 319 | ADD_LOW <= (others => 'U'); 320 | ADD_HIGH <= (others => 'U'); 321 | 322 | -- read $CFFF 323 | wait until falling_edge(PHI0); 324 | wait for ADD_valid; 325 | ADD_LOW <= (others => '1'); 326 | ADD_HIGH <= "1111"; 327 | RNW <= '1'; 328 | DATA <= (others => 'U'); 329 | wait until rising_edge(PHI0); 330 | NIO_STB <= '0'; 331 | DATA <= (others => 'Z'); 332 | wait until falling_edge(PHI0); 333 | NIO_STB <= '1'; 334 | wait for ADD_hold; 335 | ADD_LOW <= (others => 'U'); 336 | ADD_HIGH <= (others => 'U'); 337 | 338 | -- read eprom high, deselected 339 | wait until falling_edge(PHI0); 340 | wait for ADD_valid; 341 | ADD_LOW <= (others => '0'); 342 | ADD_HIGH <= "1101"; -- must become "101" 343 | RNW <= '1'; 344 | DATA <= (others => 'U'); 345 | wait until rising_edge(PHI0); 346 | NIO_STB <= '0'; 347 | DATA <= (others => 'Z'); 348 | wait until falling_edge(PHI0); 349 | NIO_STB <= '1'; 350 | wait for ADD_hold; 351 | ADD_LOW <= (others => 'U'); 352 | ADD_HIGH <= (others => 'U'); 353 | 354 | wait; 355 | end process; 356 | 357 | END; 358 | -------------------------------------------------------------------------------- /VHDL/AppleIISd_VQ44.ucf: -------------------------------------------------------------------------------- 1 | #PACE: Start of Constraints generated by PACE 2 | 3 | #PACE: Start of PACE I/O Pin Assignments 4 | NET "ADD_HIGH<10>" LOC = "P32" ; 5 | NET "ADD_HIGH<11>" LOC = "P38" ; 6 | NET "ADD_HIGH<8>" LOC = "P30" ; 7 | NET "ADD_HIGH<9>" LOC = "P31" ; 8 | NET "ADD_LOW<0>" LOC = "P13" ; 9 | NET "ADD_LOW<1>" LOC = "P12" ; 10 | NET "B<10>" LOC = "P16" ; 11 | NET "B<8>" LOC = "P20" ; 12 | NET "B<9>" LOC = "P21" ; 13 | NET "CARD" LOC = "P27" ; 14 | NET "CLK" LOC = "P37" ; 15 | NET "DATA<0>" LOC = "P41" ; 16 | NET "DATA<1>" LOC = "P42" ; 17 | NET "DATA<2>" LOC = "P43" ; 18 | NET "DATA<3>" LOC = "P44" ; 19 | NET "DATA<4>" LOC = "P1" ; 20 | NET "DATA<5>" LOC = "P3" ; 21 | NET "DATA<6>" LOC = "P5" ; 22 | NET "DATA<7>" LOC = "P7" ; 23 | NET "LED" LOC = "P23" ; 24 | NET "MISO" LOC = "P34" ; 25 | NET "MOSI" LOC = "P29" ; 26 | NET "NDEV_SEL" LOC = "P18" ; 27 | NET "NG" LOC = "P6" ; 28 | NET "NIO_SEL" LOC = "P8" ; 29 | NET "NIO_STB" LOC = "P36" ; 30 | NET "NOE" LOC = "P19" ; 31 | NET "NRESET" LOC = "P14" ; 32 | NET "NSEL" LOC = "P22" ; 33 | NET "NWE" LOC = "P40" ; 34 | NET "PHI0" LOC = "P2" ; 35 | NET "RNW" LOC = "P39" ; 36 | NET "SCLK" LOC = "P28" ; 37 | NET "WP" LOC = "P33" ; 38 | 39 | #PACE: Start of PACE Area Constraints 40 | 41 | #PACE: Start of PACE Prohibit Constraints 42 | 43 | #PACE: End of Constraints generated by PACE 44 | -------------------------------------------------------------------------------- /VHDL/SpiController.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------- 2 | -- 3 | -- Spi controller for 6502 systems 4 | -- based on a design by A. Fachat 5 | -- 6 | ---------------------------------------------------------------------------------- 7 | library IEEE; 8 | use IEEE.STD_LOGIC_1164.ALL; 9 | use IEEE.STD_LOGIC_UNSIGNED.ALL; 10 | 11 | 12 | entity SpiController is 13 | Port ( 14 | data_in : in STD_LOGIC_VECTOR (7 downto 0); 15 | data_out : out STD_LOGIC_VECTOR (7 downto 0); 16 | is_read : in STD_LOGIC; 17 | nreset : in STD_LOGIC; 18 | addr : in STD_LOGIC_VECTOR (1 downto 0); 19 | phi0 : in STD_LOGIC; 20 | ndev_sel : in STD_LOGIC; 21 | clk : in STD_LOGIC; 22 | miso: in std_logic; 23 | mosi : out STD_LOGIC; 24 | sclk : out STD_LOGIC; 25 | nsel : out STD_LOGIC; 26 | wp : in STD_LOGIC; 27 | card : in STD_LOGIC; 28 | pgm_en : out STD_LOGIC; 29 | led : out STD_LOGIC 30 | ); 31 | end SpiController; 32 | 33 | architecture Behavioral of SpiController is 34 | 35 | -------------------------- 36 | -- internal state 37 | signal spidatain: std_logic_vector (7 downto 0); 38 | signal spidataout: std_logic_vector (7 downto 0); 39 | signal sdhc: std_logic; -- is SDHC card 40 | signal inited: std_logic; -- card initialized 41 | signal pgmen: std_logic; -- enable EEPROM programming 42 | 43 | -- spi register flags 44 | signal tc: std_logic; -- transmission complete; cleared on spi data read 45 | signal bsy: std_logic; -- SPI busy 46 | signal frx: std_logic; -- fast receive mode 47 | signal ece: std_logic; -- external clock enable; 0=phi2, 1=external clock 48 | 49 | signal slavesel: std_logic := '1'; -- slave select output (0=selected) 50 | signal int_miso: std_logic; 51 | -------------------------- 52 | -- helper signals 53 | 54 | -- shift engine 55 | signal start_shifting: std_logic := '0'; -- shifting data 56 | signal shifting2: std_logic := '0'; -- shifting data 57 | signal shiftdone: std_logic; -- shifting data done 58 | signal shiftcnt: std_logic_vector(3 downto 0); -- shift counter (5 bit) 59 | 60 | -- spi clock 61 | signal clksrc: std_logic; -- clock source (phi2 or clk_7m) 62 | signal shiftclk : std_logic; 63 | 64 | begin 65 | led <= not (bsy or not slavesel); 66 | bsy <= start_shifting or shifting2; 67 | 68 | process(start_shifting, shiftdone, shiftclk) 69 | begin 70 | if (rising_edge(shiftclk)) then 71 | if (shiftdone = '1') then 72 | shifting2 <= '0'; 73 | else 74 | shifting2 <= start_shifting; 75 | end if; 76 | end if; 77 | end process; 78 | 79 | process(shiftcnt, nreset, shiftclk) 80 | begin 81 | if (nreset = '0') then 82 | shiftdone <= '0'; 83 | elsif (rising_edge(shiftclk)) then 84 | if (shiftcnt = "1111") then 85 | shiftdone <= '1'; 86 | else 87 | shiftdone <= '0'; 88 | end if; 89 | end if; 90 | end process; 91 | 92 | process(nreset, shifting2, shiftcnt, shiftclk) 93 | begin 94 | if (nreset = '0') then 95 | shiftcnt <= (others => '0'); 96 | elsif (rising_edge(shiftclk)) then 97 | if (shifting2 = '1') then 98 | -- count phase 99 | shiftcnt <= shiftcnt + 1; 100 | else 101 | shiftcnt <= (others => '0'); 102 | end if; 103 | end if; 104 | end process; 105 | 106 | inproc: process(nreset, shifting2, shiftcnt, shiftclk, spidatain, miso) 107 | begin 108 | if (nreset = '0') then 109 | spidatain <= (others => '0'); 110 | elsif (rising_edge(shiftclk)) then 111 | if (shifting2 = '1' and shiftcnt(0) = '1') then 112 | -- shift in to input register 113 | spidatain (7 downto 1) <= spidatain (6 downto 0); 114 | spidatain (0) <= int_miso; 115 | end if; 116 | end if; 117 | end process; 118 | 119 | outproc: process(nreset, shifting2, spidataout, shiftcnt, shiftclk) 120 | begin 121 | if (nreset = '0') then 122 | mosi <= '1'; 123 | sclk <= '1'; 124 | else 125 | -- clock is sync'd 126 | if (rising_edge(shiftclk)) then 127 | if (shifting2='0' or shiftdone = '1') then 128 | mosi <= '1'; 129 | sclk <= '1'; 130 | else 131 | -- output data directly from output register 132 | case shiftcnt(3 downto 1) is 133 | when "000" => mosi <= spidataout(7); 134 | when "001" => mosi <= spidataout(6); 135 | when "010" => mosi <= spidataout(5); 136 | when "011" => mosi <= spidataout(4); 137 | when "100" => mosi <= spidataout(3); 138 | when "101" => mosi <= spidataout(2); 139 | when "110" => mosi <= spidataout(1); 140 | when "111" => mosi <= spidataout(0); 141 | when others => mosi <= '1'; 142 | end case; 143 | sclk <= shiftcnt(0); 144 | end if; 145 | end if; 146 | end if; 147 | end process; 148 | 149 | 150 | -- shift operation enable 151 | shiften: process(nreset, ndev_sel, is_read, addr, frx, shiftdone) 152 | begin 153 | -- start shifting 154 | if (nreset = '0' or shiftdone = '1') then 155 | start_shifting <= '0'; 156 | elsif (rising_edge(ndev_sel) and addr="00" and (frx='1' or is_read='0')) then 157 | -- access to register 00, either write (is_read=0) or fast receive bit set (frx) 158 | -- then both types of access (write but also read) 159 | start_shifting <= '1'; 160 | end if; 161 | end process; 162 | 163 | -------------------------- 164 | -- spiclk - spi clock generation 165 | -- spiclk is still 2 times the freq. than sclk 166 | clksrc <= phi0 when (ece = '0') else clk; 167 | 168 | -- is a pulse signal to allow for divisor==0 169 | shiftclk <= clksrc when bsy = '1' else '0'; 170 | 171 | -------------------------- 172 | -- interface section 173 | -- inputs 174 | int_miso <= (miso and not slavesel); 175 | 176 | -- outputs 177 | nsel <= slavesel; 178 | pgm_en <= pgmen; 179 | 180 | tc_proc: process (ndev_sel, shiftdone) 181 | begin 182 | if (shiftdone = '1') then 183 | tc <= '1'; 184 | elsif (rising_edge(ndev_sel) and addr="00") then 185 | tc <= '0'; 186 | end if; 187 | end process; 188 | 189 | -------------------------- 190 | -- cpu register section 191 | -- cpu read 192 | cpu_read: process(addr, spidatain, tc, bsy, frx, pgmen, 193 | ece, slavesel, wp, card, sdhc, inited) 194 | begin 195 | case addr is 196 | when "00" => -- read SPI data in 197 | data_out <= spidatain; 198 | when "01" => -- read status register 199 | data_out(0) <= pgmen; 200 | data_out(1) <= '0'; 201 | data_out(2) <= ece; 202 | data_out(3) <= '0'; 203 | data_out(4) <= frx; 204 | data_out(5) <= bsy; 205 | data_out(6) <= '0'; 206 | data_out(7) <= tc; 207 | -- no register 2 208 | when "11" => -- read slave select / slave interrupt state 209 | data_out(0) <= slavesel; 210 | data_out(3 downto 1) <= (others => '0'); 211 | data_out(4) <= sdhc; 212 | data_out(5) <= wp; 213 | data_out(6) <= card; 214 | data_out(7) <= inited; 215 | when others => 216 | data_out <= (others => '0'); 217 | end case; 218 | end process; 219 | 220 | -- cpu write 221 | cpu_write: process(nreset, ndev_sel, is_read, addr, data_in, card) 222 | begin 223 | if (nreset = '0') then 224 | ece <= '0'; 225 | frx <= '0'; 226 | slavesel <= '1'; 227 | spidataout <= (others => '1'); 228 | sdhc <= '0'; 229 | inited <= '0'; 230 | pgmen <= '0'; 231 | elsif (card = '1') then 232 | sdhc <= '0'; 233 | inited <= '0'; 234 | elsif (rising_edge(ndev_sel) and is_read = '0') then 235 | case addr is 236 | when "00" => -- write SPI data out (see other process above) 237 | spidataout <= data_in; 238 | when "01" => -- write status register 239 | pgmen <= data_in(0); 240 | ece <= data_in(2); 241 | frx <= data_in(4); 242 | -- no bit 5 - 7 243 | -- no register 2 244 | when "11" => -- write slave select 245 | slavesel <= data_in(0); 246 | -- no bit 1 - 3 247 | sdhc <= data_in(4); 248 | -- no bit 5 - 6 249 | inited <= data_in(7); 250 | when others => 251 | end case; 252 | end if; 253 | end process; 254 | 255 | end Behavioral; 256 | --------------------------------------------------------------------------------