Initial commit

This commit is contained in:
s3lph 2023-03-19 02:02:29 +01:00
commit cdf5c2d1d2
Signed by: s3lph
GPG key ID: 0AA29A52FB33CFB5
6 changed files with 4135 additions and 0 deletions

30
.gitignore vendored Normal file
View file

@ -0,0 +1,30 @@
# https://github.com/github/gitignore/blob/main/KiCad.gitignore
# For PCBs designed using KiCad: https://www.kicad.org/
# Format documentation: https://kicad.org/help/file-formats/
# Temporary files
*.000
*.bak
*.bck
*.kicad_pcb-bak
*.kicad_sch-bak
*-backups
*.kicad_prl
*.sch-bak
*~
_autosave-*
*.tmp
*-save.pro
*-save.kicad_pcb
fp-info-cache
# Netlist files (exported from Eeschema)
*.net
# Autorouter files (exported from Pcbnew)
*.dsn
*.ses
# Exported BOM files
*.xml
*.csv

70
README.md Normal file
View file

@ -0,0 +1,70 @@
# AT27C040 PLCC to Commodore PET/CBM ROM Adapter PCB
* Emulate 4K or 2K ROM
* Up to 16 different images on one ROM, selectable with 4 DIP switches
* Can be produced 1-sided (but then only 4 different images can be used)
## Variations
* 4K vs 2K
* 4K: Leave center solder bridge uncut
* 2K: Cut center solder bridge
* Configuration
* unconfigurable
* Leave all solder bridges
* Do not populate the pullup resistors
* 1-sided, 2-bit configurable
* Cut the solder bridges beneath the dip switches
* Populate the pullup resistors on the front side
* 2-sided, 4-bit configurable
* Cut the solder bridges beneath the dip switches and on the bacl side
* Populate the pullup resistors on both sides
## Image Generation
Use `./mk27c040.py` to generate one 512K image from multiple individual 4K oder 2K images, e.g.:
```
./mk27c040.py -o combined.bin --00000 image1.bin --20000 image2.bin
```
You can look up the base addresses for the different DIP switch positions in the tables below.
When the output image has been created, you can flash it to the ROM chip (using `minipro` in this example):
```
minipro -p AT27C040@PLCC32 -w combined.bin
```
### DIP Switch to Base Address Mapping
When only 2 and 3 are populated:
| 2 | 3 | Base Address |
|---|---|--------------|
| 0 | 0 | `$09000` |
| 0 | 1 | `$01000` |
| 1 | 0 | `$08000` |
| 1 | 1 | `$00000` |
When all 4 switches are populated:
| 1 | 2 | 3 | 4 | Base Address |
|---|---|---|---|--------------|
| 0 | 0 | 0 | 0 | `$39000` |
| 0 | 0 | 0 | 1 | `$19000` |
| 0 | 0 | 1 | 0 | `$31000` |
| 0 | 0 | 1 | 1 | `$11000` |
| 0 | 1 | 0 | 0 | `$38000` |
| 0 | 1 | 0 | 1 | `$18000` |
| 0 | 1 | 1 | 0 | `$30000` |
| 0 | 1 | 1 | 1 | `$10000` |
| 1 | 0 | 0 | 0 | `$29000` |
| 1 | 0 | 0 | 1 | `$09000` |
| 1 | 0 | 1 | 0 | `$21000` |
| 1 | 0 | 1 | 1 | `$01000` |
| 1 | 1 | 0 | 0 | `$28000` |
| 1 | 1 | 0 | 1 | `$08000` |
| 1 | 1 | 1 | 0 | `$20000` |
| 1 | 1 | 1 | 1 | `$00000` |

72
mk27c040.py Executable file
View file

@ -0,0 +1,72 @@
#!/usr/bin/env python3
import re
import sys
import argparse
ROMSIZE = 512 * 1024
class FileMap:
def __init__(self, base: int, filename: str):
self.base = base
self.filename = filename
with open(filename, 'rb') as f:
self.data = f.read()
if len(self.data) == 0:
raise AttributeError(f'File {filename} is empty')
if len(self.data) > 4096:
raise AttributeError(f'File {filename} exceeds 4KiB')
self.end = self.base + len(self.data)
if self.base < 0 or self.end > ROMSIZE:
raise AttributeError(f'File {filename} out of bounds: {hex(self.base)[2:]}:{hex(self.end-1)[2:]}')
if self.base & 0x0fff != 0:
raise AttributeError(f'File {filename} not aligned to 4KiB boundary: {hex(self.base)[2:]}:{hex(self.end-1)[2:]}')
@staticmethod
def at(base: int):
def _filemap(f):
return FileMap(base, f)
return _filemap
def baseimage(byte):
b = int(byte, 16)
return bytearray([b]) * ROMSIZE
def create_image(ns):
buf = ns.fill
used = {}
for m in ns.maps:
if m.base in used:
raise KeyError(f'{m.filename} and {used[m.base]} are both mapped at {hex(m.base)[2:]}')
used[m.base] = m.filename
buf[m.base:m.end] = m.data
with open(ns.output, 'wb') as f:
f.write(buf)
def main():
ap = argparse.ArgumentParser()
ap.add_argument('--output', '-o', type=str, metavar='FILE', default='27c040.bin', help='Write image to FILE (default: 27c040.bin)')
ap.add_argument('--<NNNNN>', type=ValueError, metavar='FILE', help='Map FILE at the 4KiB-aligned sector starting at hex-address NNNNN.')
ap.add_argument('--fill', '-f', type=baseimage, default='FF', help='Fill unmapped areas with this hex byte (default: FF)')
# https://stackoverflow.com/a/37367814
ns, unknown = ap.parse_known_args(sys.argv[1:])
for arg in unknown:
m = re.match('^--([0-9a-fA-F]{5})$', arg)
if m is None:
continue
base = int(m.group(1), 16)
ap.add_argument(arg, type=FileMap.at(base), dest='maps', action='append')
ns = ap.parse_args(sys.argv[1:])
create_image(ns)
if __name__ == '__main__':
main()

1238
pcb.kicad_pcb Normal file

File diff suppressed because it is too large Load diff

435
pcb.kicad_pro Normal file
View file

@ -0,0 +1,435 @@
{
"board": {
"design_settings": {
"defaults": {
"board_outline_line_width": 0.09999999999999999,
"copper_line_width": 0.19999999999999998,
"copper_text_italic": false,
"copper_text_size_h": 1.5,
"copper_text_size_v": 1.5,
"copper_text_thickness": 0.3,
"copper_text_upright": false,
"courtyard_line_width": 0.049999999999999996,
"dimension_precision": 4,
"dimension_units": 3,
"dimensions": {
"arrow_length": 1270000,
"extension_offset": 500000,
"keep_text_aligned": true,
"suppress_zeroes": false,
"text_position": 0,
"units_format": 1
},
"fab_line_width": 0.09999999999999999,
"fab_text_italic": false,
"fab_text_size_h": 1.0,
"fab_text_size_v": 1.0,
"fab_text_thickness": 0.15,
"fab_text_upright": false,
"other_line_width": 0.15,
"other_text_italic": false,
"other_text_size_h": 1.0,
"other_text_size_v": 1.0,
"other_text_thickness": 0.15,
"other_text_upright": false,
"pads": {
"drill": 0.762,
"height": 1.524,
"width": 1.524
},
"silk_line_width": 0.15,
"silk_text_italic": false,
"silk_text_size_h": 1.0,
"silk_text_size_v": 1.0,
"silk_text_thickness": 0.15,
"silk_text_upright": false,
"zones": {
"45_degree_only": false,
"min_clearance": 0.508
}
},
"diff_pair_dimensions": [
{
"gap": 0.0,
"via_gap": 0.0,
"width": 0.0
}
],
"drc_exclusions": [],
"meta": {
"version": 2
},
"rule_severities": {
"annular_width": "error",
"clearance": "error",
"copper_edge_clearance": "error",
"courtyards_overlap": "error",
"diff_pair_gap_out_of_range": "error",
"diff_pair_uncoupled_length_too_long": "error",
"drill_out_of_range": "error",
"duplicate_footprints": "warning",
"extra_footprint": "warning",
"footprint_type_mismatch": "error",
"hole_clearance": "error",
"hole_near_hole": "error",
"invalid_outline": "error",
"item_on_disabled_layer": "error",
"items_not_allowed": "error",
"length_out_of_range": "error",
"malformed_courtyard": "error",
"microvia_drill_out_of_range": "error",
"missing_courtyard": "ignore",
"missing_footprint": "warning",
"net_conflict": "warning",
"npth_inside_courtyard": "ignore",
"padstack": "error",
"pth_inside_courtyard": "ignore",
"shorting_items": "error",
"silk_over_copper": "warning",
"silk_overlap": "warning",
"skew_out_of_range": "error",
"through_hole_pad_without_hole": "error",
"too_many_vias": "error",
"track_dangling": "warning",
"track_width": "error",
"tracks_crossing": "error",
"unconnected_items": "error",
"unresolved_variable": "error",
"via_dangling": "warning",
"zone_has_empty_net": "error",
"zones_intersect": "error"
},
"rules": {
"allow_blind_buried_vias": false,
"allow_microvias": false,
"max_error": 0.005,
"min_clearance": 0.0,
"min_copper_edge_clearance": 0.0,
"min_hole_clearance": 0.25,
"min_hole_to_hole": 0.25,
"min_microvia_diameter": 0.19999999999999998,
"min_microvia_drill": 0.09999999999999999,
"min_silk_clearance": 0.0,
"min_through_hole_diameter": 0.3,
"min_track_width": 0.19999999999999998,
"min_via_annular_width": 0.049999999999999996,
"min_via_diameter": 0.39999999999999997,
"solder_mask_clearance": 0.0,
"solder_mask_min_width": 0.0,
"use_height_for_length_calcs": true
},
"track_widths": [
0.0,
0.3,
0.8
],
"via_dimensions": [
{
"diameter": 0.0,
"drill": 0.0
}
],
"zones_allow_external_fillets": false,
"zones_use_no_outline": true
},
"layer_presets": []
},
"boards": [],
"cvpcb": {
"equivalence_files": []
},
"erc": {
"erc_exclusions": [],
"meta": {
"version": 0
},
"pin_map": [
[
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
2,
0,
1,
0,
0,
1,
0,
2,
2,
2,
2
],
[
0,
0,
0,
0,
0,
0,
1,
0,
1,
0,
1,
2
],
[
0,
1,
0,
0,
0,
0,
1,
1,
2,
1,
1,
2
],
[
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
2
],
[
1,
1,
1,
1,
1,
0,
1,
1,
1,
1,
1,
2
],
[
0,
0,
0,
1,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
2,
1,
2,
0,
0,
1,
0,
2,
2,
2,
2
],
[
0,
2,
0,
1,
0,
0,
1,
0,
2,
0,
0,
2
],
[
0,
2,
1,
1,
0,
0,
1,
0,
2,
0,
0,
2
],
[
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2
]
],
"rule_severities": {
"bus_definition_conflict": "error",
"bus_entry_needed": "error",
"bus_label_syntax": "error",
"bus_to_bus_conflict": "error",
"bus_to_net_conflict": "error",
"different_unit_footprint": "error",
"different_unit_net": "error",
"duplicate_reference": "error",
"duplicate_sheet_names": "error",
"extra_units": "error",
"global_label_dangling": "warning",
"hier_label_mismatch": "error",
"label_dangling": "error",
"lib_symbol_issues": "warning",
"multiple_net_names": "warning",
"net_not_bus_member": "warning",
"no_connect_connected": "warning",
"no_connect_dangling": "warning",
"pin_not_connected": "error",
"pin_not_driven": "error",
"pin_to_pin": "warning",
"power_pin_not_driven": "error",
"similar_labels": "warning",
"unannotated": "error",
"unit_value_mismatch": "error",
"unresolved_variable": "error",
"wire_dangling": "error"
}
},
"libraries": {
"pinned_footprint_libs": [],
"pinned_symbol_libs": []
},
"meta": {
"filename": "pcb.kicad_pro",
"version": 1
},
"net_settings": {
"classes": [
{
"bus_width": 12.0,
"clearance": 0.2,
"diff_pair_gap": 0.25,
"diff_pair_via_gap": 0.25,
"diff_pair_width": 0.2,
"line_style": 0,
"microvia_diameter": 0.3,
"microvia_drill": 0.1,
"name": "Default",
"pcb_color": "rgba(0, 0, 0, 0.000)",
"schematic_color": "rgba(0, 0, 0, 0.000)",
"track_width": 0.25,
"via_diameter": 0.8,
"via_drill": 0.4,
"wire_width": 6.0
}
],
"meta": {
"version": 2
},
"net_colors": null
},
"pcbnew": {
"last_paths": {
"gencad": "",
"idf": "",
"netlist": "",
"specctra_dsn": "",
"step": "",
"vrml": ""
},
"page_layout_descr_file": ""
},
"schematic": {
"annotate_start_num": 0,
"drawing": {
"default_line_thickness": 6.0,
"default_text_size": 50.0,
"field_names": [],
"intersheets_ref_own_page": false,
"intersheets_ref_prefix": "",
"intersheets_ref_short": false,
"intersheets_ref_show": false,
"intersheets_ref_suffix": "",
"junction_size_choice": 3,
"label_size_ratio": 0.375,
"pin_symbol_size": 25.0,
"text_offset_ratio": 0.15
},
"legacy_lib_dir": "",
"legacy_lib_list": [],
"meta": {
"version": 1
},
"net_format_name": "",
"ngspice": {
"fix_include_paths": true,
"fix_passive_vals": false,
"meta": {
"version": 0
},
"model_mode": 0,
"workbook_filename": ""
},
"page_layout_descr_file": "",
"plot_directory": "",
"spice_adjust_passive_values": false,
"spice_external_command": "spice \"%I\"",
"subpart_first_id": 65,
"subpart_id_separator": 0
},
"sheets": [
[
"e63e39d7-6ac0-4ffd-8aa3-1841a4541b55",
""
]
],
"text_variables": {}
}

2290
pcb.kicad_sch Normal file

File diff suppressed because it is too large Load diff