mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-31 11:17:01 -07:00
Compare commits
130 Commits
FluxEngine
...
FluxEngine
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
adbcb2cd31 | ||
|
|
c47a563790 | ||
|
|
04c09d1a5b | ||
|
|
323da8272a | ||
|
|
38700c79fc | ||
|
|
d504d1890a | ||
|
|
d53e757cfb | ||
|
|
4983239458 | ||
|
|
376985828a | ||
|
|
dce0a26820 | ||
|
|
14e0a67e7d | ||
|
|
1656947764 | ||
|
|
647862cdbd | ||
|
|
4a8d83838c | ||
|
|
8acf8e181d | ||
|
|
2df9920209 | ||
|
|
1a6c6b5420 | ||
|
|
edc56d44d6 | ||
|
|
ef4eff0195 | ||
|
|
df8d45bf66 | ||
|
|
89a27619ff | ||
|
|
387a86969a | ||
|
|
acb5059d17 | ||
|
|
a4002d2617 | ||
|
|
a63a90bbd0 | ||
|
|
d25f96dd24 | ||
|
|
e8febe6508 | ||
|
|
ad3a930c6a | ||
|
|
be41c1de76 | ||
|
|
d528978667 | ||
|
|
827fcf69d2 | ||
|
|
711ff545e0 | ||
|
|
5befa31050 | ||
|
|
8e5c2d0ebb | ||
|
|
f95fceeb3d | ||
|
|
003b20dbf0 | ||
|
|
cd9bbaa4b6 | ||
|
|
71e622bf72 | ||
|
|
2a065a08df | ||
|
|
6087228378 | ||
|
|
efd74e0d7b | ||
|
|
b68a9dcc4f | ||
|
|
008855daa9 | ||
|
|
7a9d36de2a | ||
|
|
c56e982c9a | ||
|
|
002cc171a2 | ||
|
|
32e721b47a | ||
|
|
1e82f697a9 | ||
|
|
fa09631e32 | ||
|
|
e06436ce1e | ||
|
|
b2f443e1ad | ||
|
|
2e07be0cf7 | ||
|
|
bf0b14d094 | ||
|
|
c9f5803194 | ||
|
|
5293560c02 | ||
|
|
c49823aa9d | ||
|
|
c4ef4882ae | ||
|
|
a8eca06cf0 | ||
|
|
065257b5aa | ||
|
|
29bdfc043a | ||
|
|
933ffe7ab4 | ||
|
|
e517f28563 | ||
|
|
91ffcf59c3 | ||
|
|
51c618f325 | ||
|
|
9dc1067032 | ||
|
|
9e75dc3af1 | ||
|
|
efa4c933b3 | ||
|
|
6af80d1e5e | ||
|
|
0c48897814 | ||
|
|
60e5e35947 | ||
|
|
86c4e959ca | ||
|
|
b0c675c589 | ||
|
|
d77841c3b7 | ||
|
|
4ed1fb6bac | ||
|
|
bcc9e9d9a5 | ||
|
|
ec327e25a4 | ||
|
|
d0ed5b32f7 | ||
|
|
7c66e1b0d4 | ||
|
|
4475e9f085 | ||
|
|
5c9639ec5a | ||
|
|
792cc88192 | ||
|
|
21fe586724 | ||
|
|
5a0fb2761a | ||
|
|
ef4581ed39 | ||
|
|
73419704c2 | ||
|
|
a8b92d4780 | ||
|
|
98140b0646 | ||
|
|
4429ce1f84 | ||
|
|
1f50941a2c | ||
|
|
a7de04848c | ||
|
|
c264fec6e9 | ||
|
|
4488b2542f | ||
|
|
2f1a5189d6 | ||
|
|
effaeff51e | ||
|
|
1210549f59 | ||
|
|
7200de9702 | ||
|
|
5dd5c8516a | ||
|
|
f7fb2a844b | ||
|
|
20b1b2a4a8 | ||
|
|
f8b8bc2295 | ||
|
|
2d4d56d09f | ||
|
|
39599b76c8 | ||
|
|
c2c40ccfbb | ||
|
|
ab42eb23f4 | ||
|
|
05eff0e528 | ||
|
|
23311b4b68 | ||
|
|
5e97df8d15 | ||
|
|
898e8c551c | ||
|
|
ad69c6bd27 | ||
|
|
661399cc83 | ||
|
|
edbb4b1daa | ||
|
|
6389e8a756 | ||
|
|
c187b79d80 | ||
|
|
edbe624c5a | ||
|
|
44e2334815 | ||
|
|
b448ab7917 | ||
|
|
072a097003 | ||
|
|
a66e704bab | ||
|
|
ed0d578b18 | ||
|
|
32bb956710 | ||
|
|
f436d6b582 | ||
|
|
d2f8c27cb6 | ||
|
|
eaa3c57425 | ||
|
|
549f12a2ab | ||
|
|
aea254fbe7 | ||
|
|
8ee6eed4dc | ||
|
|
3094c5c919 | ||
|
|
1e012699af | ||
|
|
91d6e9aeb9 | ||
|
|
a40b26ff46 |
@@ -15,7 +15,7 @@ install:
|
||||
|
||||
build_script:
|
||||
- make
|
||||
- zip -9 fluxengine.zip fluxengine.exe brother120tool.exe FluxEngine.cydsn/CortexM3/ARM_GCC_541/Release/FluxEngine.hex
|
||||
- zip -9 fluxengine.zip fluxengine.exe brother120tool.exe brother240tool.exe FluxEngine.cydsn/CortexM3/ARM_GCC_541/Release/FluxEngine.hex
|
||||
|
||||
artifacts:
|
||||
- path: fluxengine.zip
|
||||
|
||||
41
.github/workflows/ccpp.yml
vendored
Normal file
41
.github/workflows/ccpp.yml
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
name: C/C++ CI
|
||||
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
build-linux:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
with:
|
||||
fetch-depth: 1
|
||||
- name: apt
|
||||
run: sudo apt install libusb-1.0-0-dev libsqlite3-dev ninja-build
|
||||
- name: make
|
||||
run: make
|
||||
|
||||
build-macos:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
with:
|
||||
fetch-depth: 1
|
||||
- name: brew
|
||||
run: brew install sqlite pkg-config libusb ninja
|
||||
- name: make
|
||||
run: make
|
||||
|
||||
# build-windows:
|
||||
# runs-on: windows-latest
|
||||
# steps:
|
||||
# - uses: numworks/setup-msys2@v1
|
||||
# with:
|
||||
# path-type: inherit
|
||||
# - uses: actions/checkout@v1
|
||||
# - name: pacman
|
||||
# run: |
|
||||
# msys2do pacman -S --noconfirm --needed make ninja mingw-w64-i686-libusb mingw-w64-i686-sqlite3 mingw-w64-i686-zlib mingw-w64-i686-gcc zip
|
||||
# - name: build
|
||||
# run: |
|
||||
# msys2do make
|
||||
|
||||
39
.travis.yml
39
.travis.yml
@@ -1,39 +0,0 @@
|
||||
language: shell
|
||||
git:
|
||||
depth: 1
|
||||
|
||||
matrix:
|
||||
include:
|
||||
-
|
||||
os: linux
|
||||
sudo: false
|
||||
dist: xenial
|
||||
compiler: gcc
|
||||
env: CXX=g++-8
|
||||
script:
|
||||
- make
|
||||
-
|
||||
os: osx
|
||||
osx_image: xcode10.2
|
||||
compiler: clang
|
||||
env:
|
||||
- HOMEBREW_NO_INSTALL_CLEANUP=1
|
||||
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- llvm-toolchain-precise-3.8
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- ninja-build
|
||||
- libusb-1.0-0-dev
|
||||
- libsqlite3-dev
|
||||
- g++-8
|
||||
homebrew:
|
||||
packages:
|
||||
- ninja
|
||||
|
||||
script:
|
||||
- make
|
||||
|
||||
|
||||
@@ -1,254 +1,254 @@
|
||||
:4000000000800020110000005D0D00005D0D0000064A08B5136843F020031360044B1A6803F53F5302331A6000F0B6FEE8460040FA46004010B5054C237833B9044B13B19E
|
||||
:400040000448AFF300800123237010BD6081FF1F00000000242E0000084B10B51BB108490848AFF300800848036803B910BD074B002BFBD0BDE81040184700BF00000000F7
|
||||
:400080006481FF1F242E0000C880FF1F0000000072B6034A13680133136062B6704700BF8081FF1F0A4A0B4B516801310B40002BBEBF03F1FF3363F00F030133536051688E
|
||||
:4000C0009368994202BF024B01221A73704700BF8081FF1F0F0000800A4A0B4B916801310B40002BBEBF03F1FF3363F00F030133936091685368994202BF024B01221A7381
|
||||
:40010000704700BF8081FF1F0F000080024B012200205A7302F024B98081FF1F10B5C4B2204601F007FA0128FAD110BD70B5C4B220460E4601F006FA314605460246204646
|
||||
:4001400001F066FA204601F0F5F90128FAD0284670BD000038B5094CA57B3DB9012002F0A5F84FF47A7000F08FFFE573236823610123A373BDE8384000F0C4BF8081FF1F58
|
||||
:4001800038B50446C5B2284602F09CF8012000F091FF44F00200C0B202F094F8012000F089FF284602F08EF8BDE83840062000F06BBF000038B5044D0024285D013400F0EE
|
||||
:4001C00029FF102CF9D138BD9481FF1F0FB400B593B014AB53F8042B402102A8019302F013FA02A802F04DF802F057F813B05DF804EB04B07047000010B5044601780648AD
|
||||
:40020000FFF7E4FF0420FFF789FF62782146BDE81040042001F0AAB9362E000007B50023ADF804308DF80600032301A88DF80530FFF7E2FF03B05DF804FB0000F8B5234C6B
|
||||
:400240000646FFF787FFE37B93B92148FFF7BEFF02F032F818B90120FFF792FFF8E70120FFF78EFF01200023E073636200F022FF3246616A1748FFF7A9FF144D0027636AD6
|
||||
:400280009E421BD002F018F828B16B6A13B11248FFF79CFF6762636A9E4205DD0020FFF76FFF6B6A013305E005DA0120FFF768FF6B6A013B6B6200F025FFE0E7322000F0F2
|
||||
:4002C000E3FEBDE8F8400548FFF780BF8081FF1F432E00004A2E0000672E0000852E00002DE9F04F97B062B600F076FFBE49042000F09AFFBD4801F0EBFFBD4802F018F8BA
|
||||
:40030000BC4802F061F8002002F030F801F0B8FF0221002001F0C4F8B74D0321084600F0D1FE2E462C4600F0EDFEAB7B5BB12A692B689B1A41F28832934204D9002001F0E9
|
||||
:40034000B5FF0023AB7301F0E3F818B9AB48FFF73DFF04E001F0E2F80028F7D109E001F0D7F80028FBD0A648FFF730FF032001F03BF9032001F0DEF80128D4D1A14903206B
|
||||
:40038000FFF7D4FE94F828109F48FFF71FFF94F82830023B102B00F24B83DFE813F0110049031A00490320004903380049035C004903A4014903100349032F0349033B0369
|
||||
:4003C00003238DF818308DF8193008238DF81A301CE394F82A00FFF731FF8C4B13E3FFF7B9FE00236373637B002BFCD0002373733268637B002BFCD0336807218DF8181037
|
||||
:400400009B1A04218DF81910ADF81A30FEE20220FFF784FE4FF000090DF1180A4FF480780027C8EB0903DA1907F80A200137402FF9D10220FFF772FE3A465146022001F003
|
||||
:4004400095F8B8F10108EBD109F10109B9F1400FE4D16F4BAEE294F82A0001F07BFF606AFFF7ECFE012001F087FF01F0D9FF694BDFF8A8811A78002742F004021A701A7898
|
||||
:4004800042F001021A701A7802F0FE021A701A7802F0FE021A7001F0C7FF0220FFF73EFE41F6FF734FF480420121022001F024FF84F8680000F094FD08F807000137102F6D
|
||||
:4004C000F8D1DFF85CA100270AF15D081FFA88F90137102F14BF3A4600221AF8010F22440623127D402100F0AFFD4A4646F24B419AF8000000F0BAFD09F14009102F1FFAED
|
||||
:4005000089F9E5D14448FFF761FE00237373637B002BFCD000271422394606A87773DFF8049102F03EF84023099338464FF0FF337760CDF82090B360377301F01DFF012097
|
||||
:4005400001F060FF736896F868003344197D00F0FFFC96F8680000F0BDFC012196F8680000F090FC636813B96B7B002BFAD0002794F82BA0A76094F80CB0BBF1000F6CD1F8
|
||||
:4005800000F0C0FD6B7B43B1BAF1010A85F80DB003D162E02B7B002B5FD1A26863689A42F8D04FF0000BA36806A808EB83135B440693CBF14003079300F054FA079B0137BF
|
||||
:4005C000C3F140039B44099B5FFA8BFB002B34D1022000F0AFFF012826D0637B002B3CD12B7B002BF4D038E0910000000D010000A5000000D90000008081FF1F932E0000D3
|
||||
:40060000A62E0000A881FF1FB02E0000282E00002A2E00009B640040BF2E00009481FF1F9381FF1FF085FF1F4022BE49022000F09DFF4023CDF820900993BBF13F0FB2D9DF
|
||||
:40064000A268B94B01321340002BBEBF03F1FF3363F00F030133A3608DE7002001F0D2FE042194F8680000F07FFC94F8680000F08BFC0028F9D106A800F028FA0220FFF76E
|
||||
:400680004DFDDDF82480B8F1400F06D0C8F1400292B2A449022000F069FF099A32F0400203D11146022000F061FF0220FFF736FDFFF780FD237B33B19C48FFF787FD02209F
|
||||
:4006C000FFF7ACFD06E09A4B05A81B88ADF81430FFF792FD627B3946237B9648CDF80080FFF774FDA7E1E76A17F03F0701D003209FE195F82A0001F02DFE012001F042FE8F
|
||||
:4007000001F08EFE8C4BDFF834821A7802F0FB021A701A7842F001021A701A7802F0FE021A701A7802F0FE021A7001F07DFE686AFFF784FD01214FF4804341F6FF7208468D
|
||||
:4007400001F026FE85F8680000F04AFC08F807000137102FF8D1DFF8E891002709F15D031FFA83F803930137102F14BF3A46002219F8010F22440523127D402100F064FC2C
|
||||
:40078000414646F24E4299F8000000F06FFC08F14008102F1FFA88F8E5D1F36A00279B09142239464FF0FF3806A877600293C6F80880377301F0F5FE402301200993B946CF
|
||||
:4007C00000F012FFBA466268574B01321340002BBCBF03F1FF3363F00F03A168B8BF01338B4200F08F80BAF1000F07D0237B002B40F0A8806B7B002B40F0A480079B002B71
|
||||
:4008000034D1B9F1000F0BD07F2246495A540133402BFAD10691079328E0BAF1000F06D1012000F087FE01288346F6D107E0237B002B40F087806B7B002BF1D082E0394921
|
||||
:40084000FFF774FC8146374B07905846069300F0CBFEB9F13F0F07F1010706DD029BDB1BD3F1000949EB030900E0D946079BDBB16368039A06A802EB8312099BC3F1400367
|
||||
:400880001344089300F031F9099B6BB96A68264B01321340002BBEBF03F1FF3363F00F030133636040230993A36801332AD16B680F2B27D14FF00008C5F8088001F096FD23
|
||||
:4008C00085F80C80AB6895F868002B44197D00F03FFB95F8680000F0FDFA012195F8680000F0D0FA85F80D80637B002BFCD04FF00008012086F80D8001F032FD404601F022
|
||||
:4009000041FD02E0BAF1000F05D0237BD3B96B7BC3B94FF0010AA36843453FF454AFD5F8088050E7F085FF1F0F000080C42E00002C2E0000DE2E00009E6400409481FF1FEE
|
||||
:400940009381FF1F01F058FD012001F01BFD002001F006FD042194F8680000F005FB94F8680000F011FB0028F9D196F8680000F09FFAB9F1000F16D1029BBB420ADD012015
|
||||
:4009800000F0D8FD01288046F6D12E49FFF7CEFB3F2803DC012000F061FE04E0404600F023FE0137E8E7FFF705FC237B0BB102203FE0254B1B8805A8ADF8143027E094F880
|
||||
:4009C0002A0001F0C7FC606AFFF738FC1F48FFF7FDFB00236373637B002BFCD0012001F0BFFC00237373637B002BFCD0002001F0B7FC1748FFF7EAFB164B04E00020E073A1
|
||||
:400A0000FFF71CFC144B1B88ADF8183006A8FFF7F3FB10E094F82A0094F8B034834205D085F8B00401F0A2FC0023EB730B4BEAE70120FFF7F3FB032000F0D6FD0848FFF7DE
|
||||
:400A4000C5FB70E4F085FF1F2E2E0000F72E0000052F0000302E0000322E0000342E0000122F000010B54268002A2ED0C368002B2BD00368048A591C01601B78013A13F031
|
||||
:400A8000800F817C42601DBF03F0010242EA84030231083114BF43F0020343EA0423817414BF03820382837C072BDCD9028A083B42FA03F38268511C81601370C368013BDD
|
||||
:400AC000C360837C083B8374CDE710BD07B5827C42B102AA002102F8011D026001224260FFF7C0FF03B05DF804FB30B543686BB3C2685AB3827C072A0CD8046890F9105057
|
||||
:400B0000611C01602178013B41EA05210832018243608274827C018AA2F108042141CBB2090608D5C3F3801363F07F03023A03F08103827402E08474002BD7D08268511C9E
|
||||
:400B400081601370C368013BC360CFE730BD0000F8B572B6634B61221A70A3F5F06301221A80192406229C7083F88022522203F5C0731A705C4B5D4A1B785D4EDBB2137059
|
||||
:400B800040F618025B4B00251A8041F2512223F8022C33784FF4F07003F0010343EA450501F036FC013C05F0030521D0032DF0D1514B4FF480721A8007221A704F4A0024BB
|
||||
:400BC00048211470917002221C705C7103F8032C4B4A4C4D1378062643F001031370414B01221A70484A137843F02003137000E0FEE706FB045300219A881868013401F08C
|
||||
:400C0000D0FC082CF5D180224049414801F0BEFC404D4148002450F8041F04F1105303F1420221F0FF064333C9B20B4452005B0002329A4206D012F8027C12F801EC07F8F3
|
||||
:400C400006E0F5E7A8420C44E5D1344B00221A60334B34491A68344B344C1A60344A137843F002031370137C43F002031374314B1A7842F040021A700A7842F010020A7053
|
||||
:400C80002D4A07CA03C42D49228008682C4A28341060097911712B4A07CA03C422802A4AE83C07CA03C42280284A083407CA03C4274922800A78A4F6785442F008020A70E0
|
||||
:400CC000244A01F5AA5112780C31D2B202F00700120908704A70204A442111700FCB07C42380F8BD004800400F010049A1460040254200402242004004400040064000405A
|
||||
:400D0000A2430040172F0000E8460040A4050048800A014080000048FCFFFF47007600405C060048C243004008760040C051004003500140A04300402406004830060048BA
|
||||
:400D4000CB51004038060048440600485006004822430040CF0100497658004008B501F0E9FB03680C2B00D1FEE7FEE7084908B50B68084A1844821A802A01DC086005E027
|
||||
:400D800001F0D8FB0C2303604FF0FF33184608BDCC80FF1F1087FF1F80B51148114B0025C0B1A3F1100192C922460439161BB74204D051F8046F42F8046BF7E7114653F822
|
||||
:400DC000046C8C1AA64202D041F8045BF9E701381033E5E701F0B4FBFFF782FAFEE700BF01000000D8300000124A134B10B51A60124A134C1368134843F4007313600023DA
|
||||
:400E0000032B98BF54F823204FEA830188BF0E4A0133302B4250F3D10C4B1A780C4B1A700C4B084A1A60FFF793FEBDE8104000F013B800BF0004FA050CED00E014ED00E0BD
|
||||
:400E4000000000000080FF1F5D0D0000BC760040C080FF1F08ED00E0074A7F23802113705170064A013BDBB202F80839002BF9D1034A1370704700BFD080FF1FF87B00403D
|
||||
:400E80000078004017280FD8084B0001C25C11B142F0200201E002F0DF02C254C25C42F00102C25400207047012070471070004017280BD8064B0001C25C02F0FE02C25490
|
||||
:400EC000C25C02F0DF02C25400207047012070471070004017280DD8074900010B4603441A7942F004021A71435C43F00103435400207047012070471070004017280BD81B
|
||||
:400F0000064A0001835C490003F0F10301F00E011943815400207047012070471070004041F6FF73994208BF4FF400519A4208BF4FF4005217289FBFC00000F1804000F597
|
||||
:400F4000EC4081809ABFC280002001207047000017289FBF034B00011954002088BF0120704700BF1970004017289FBF054B00011A5C01F007019DBF1143195400200120D6
|
||||
:400F8000704700BF1470004017289FBF034B0001185C00F0070088BFFF20704714700040172810B51AD8C00001F07F0100F1804441EAC21204F5EC44D2B222709DF80820E8
|
||||
:400FC00003F00F0343EA0213DBB263709DF80C30002003F00F03A370E07010BD012010BD10B501F01DFA0A4A5378182B0AD91478013B5370E30003F1804303F5F0431B7841
|
||||
:40100000137000E0FF2401F00FFA204610BD00BFD080FF1F030610B5044611D401F000FA084AE300117803F1804303F5F04319705378147001335370BDE8104001F0F4B9E6
|
||||
:4010400010BD00BFD080FF1F30B504060CD411F4704509D1C40004F1804404F5F0442180A270E370284630BD012030BD03065FBFC00000F1804000F5F04081805ABFC280E1
|
||||
:40108000002001207047000038B50446084DB4F5004F05D9286801F0BBF9A4F50044F6E7034B58686043BDE8384001F0B1B900BFD880FF1F024B1B7A584301F0A9B900BFFA
|
||||
:4010C000D880FF1F0E4B00F003001A78490102F0FC02104318701A7801F0600142F080021A701A7802F07F021A701A7802F09F020A431A701A7842F010021A70704700BF04
|
||||
:4011000083430040014B01221A70704784430040044B00F00F021B6853F8220043F82210704700BF08ED00E0054A00F01F00126800F1100352F8230042F82310704700BFCE
|
||||
:4011400008ED00E000F01F0000F16040490100F56440C9B2017070470F4B10B50F4900240F205C609C60DC601C615C61FFF7D0FF0B4A136843F0040313600A4B4FF47A72B6
|
||||
:40118000DB68B3FBF2F3084A1360084B4FF400421C60C3F8E82010BD3486FF1F0512000010E000E0D880FF1F14E000E018E000E0024A136843F002031360704710E000E0D6
|
||||
:4011C00008B5FFF7F5FF034A136843F00103136008BD00BF10E000E010B5054CA3691BB9FFF7BAFF0123A361BDE81040FFF7E8BF3486FF1F024B1868C0F30040704700BF15
|
||||
:4012000010E000E038B5FFF7F5FF012808D1054D002455F8243003B198470134052CF8D138BD00BF3886FF1F024B03EB80035868596070473486FF1F134B144A1B78DBB2FA
|
||||
:401240000360127843EA0223114A0360127843EA0243104A0360127843EA026303600E4B0E4A1B78DBB24360127843EA02230C4A4360127843EA02430A4A4360127843EA46
|
||||
:4012800002634360704700BF0301004904010049EC4600400201004901010049000100490501004906010049F8B501F0B9F8444A01271378022643F001031370137C414C95
|
||||
:4012C00043F001031374404B02F5E3521F700B3203F8946C1378054603F07F0313700020FFF7E8FE2378394A03F0F90323701378384603F0DF03137023783B432370FFF745
|
||||
:40130000D9FE2820FFF7D6FE314B30461A7802F07F021A701A7802F0BF021A70237833432370FFF7C7FE23782A4A43F004032370002313702846537001F076F807211720A4
|
||||
:40134000FFF700FF24491720FFF7EEFE07211820FFF7F8FE21491820FFF7E6FE07211520FFF7F0FE1E491520FFF7DEFE07210320FFF7E8FE1B490320FFF7D6FE07210420B7
|
||||
:40138000FFF7E0FE18490420FFF7CEFE07210520FFF7D8FE15490520FFF7C6FE07210620FFF7D0FE12490620FFF7BEFE07210C20FFF7C8FEBDE8F8400E490C20FFF7B4BE9F
|
||||
:4013C000A5430040944300409D60004012600040F851004084600040031B00003D190000011B0000351A0000611A0000911A0000C91A0000071B000008B51D4B1D4A1870F4
|
||||
:40140000002313701C4A13701C4A13701C4A13701C4A13701C4A13701C4A13701C4B4FF400021A604FF080721A604FF400121A6008221A6010221A6020221A6040221A6008
|
||||
:40144000144B19B91A7802F0FE0202E01A7842F001021A70104B03221A70802203F8202C012000F0D5FF0D4B04221A7008BD00BF6C86FF1F7286FF1F7086FF1F7186FF1FD1
|
||||
:401480006D86FF1F5C86FF1F6F86FF1FE486FF1F00E100E009600040286000401260004070B5074C054623780E461BB9FFF7FCFE0123237031462846BDE87040FFF79CBFE4
|
||||
:4014C0005086FF1F0A4A002313700A4A13700A4A13700A4A13700A4A13700A4A13700A4A13700A4B03221A70802203F8202C70477286FF1F7086FF1F7186FF1F6D86FF1F00
|
||||
:401500005C86FF1F6F86FF1FE486FF1F28600040014B1878704700BF7186FF1F044B1A7802F0FF001AB118780022C0B21A7070477086FF1F024A0C2303FB002040787047C3
|
||||
:401540007886FF1F431E072B0CD8074A064B00010344805C5B7800F00F0043EA0020023880B2704700207047FC5F0040431E072BF0B531D8194B0C2505FB0035EC88184F78
|
||||
:40158000A4B2C4F50074A2424FF00C0404FB003488BFEA88E67884BFC2F5007292B2104C46EA12260501EE552C44D6B2667041B90C2202FB0030002343704379DBB2A37019
|
||||
:4015C000F0BD0E46074F2F44751AADB2AA42EFD916F8015B3D72F7E7F0BD00BF7886FF1FFC5F004070600040431E072B0AD8064A0C2303FB002300225A705A79034BD2B2AF
|
||||
:4016000000011A54704700BF7886FF1FFE5F004038B505461446D1B1431E072B19D8FFF791FFA04203D22846FFF78CFF04460A4609482B011844531A9BB29C4203D9037AE4
|
||||
:4016400002F8013BF7E72846FFF7CEFF02E00C4600E00024204638BD70600040431E072B9FBF024B000108221A547047FE5F004030B51A4A1A491B4D0878138803449BB294
|
||||
:401680001380194A00231488D8B2A4B27CB1082B0CD050680078C0B2E85450680133013050601088013880B21080ECE718460B780E4C082B0E4A00D040B10E4D2B7883F050
|
||||
:4016C00080032B700F232370022301E0022323701370094B1870087030BD00BFE886FF1FE486FF1F006000406086FF1F5D86FF1F7286FF1F6E86FF1FE586FF1F074B0222E6
|
||||
:401700001A70074B80221A70064B0F221A70064A00231370054A0120137070477286FF1F6E86FF1F5D86FF1FE486FF1FE586FF1F30B5164B16491B780A8803F00F03023BAF
|
||||
:40174000DBB21A4492B20A80124C134A0020118889B279B173B15568215C013BC9B229705168DBB20131516011880130013989B21180ECE7094A1370094A137883F08003B3
|
||||
:401780001370084B0B221A7030BD00BF29600040E886FF1F006000406086FF1FE586FF1F6E86FF1F5D86FF1F064A06231370064A01201370054B80221A70054B00221A70F3
|
||||
:4017C000704700BF7286FF1F5D86FF1F6E86FF1FE586FF1F054B9A683AB19A68044910709A680988518000229A6070476086FF1FE886FF1F08B5124B1A78D2B21A701B78A1
|
||||
:40180000DBB21A0602D50F4A137008BD0220FFF7E1FF0D4B1B7803F06003202B05D0402B06D043B900F0D4FB04E000F057FE01E000F008FD10B9034B03221A7008BD00BFE5
|
||||
:40184000286000405D86FF1F0060004008B5084A084B0120197813880B449BB21380064B00221A70FFF7B6FF044B03221A7008BDE886FF1FE486FF1F7286FF1F5D86FF1F8B
|
||||
:4018800008B50C4B1B78DBB2042B07D0062B09D0022B0DD1BDE80840FFF7D8BFBDE80840FFF746BF0320FFF795FF034B03221A7008BD00BF7286FF1F5D86FF1F08B5054B25
|
||||
:4018C000002201201A70FFF785FF034B03221A7008BD00BF7286FF1F5D86FF1F08B50A4B1A7832B11A78094942F080020A7000221A70074B002201201A70FFF76BFF054BF5
|
||||
:4019000003221A7008BD00BF5C86FF1F086000407286FF1F5D86FF1F074B1B78DBB2042B05D0062B05D0022B05D1FFF7A1BEFFF7C5BFFFF7D3BF70477286FF1F38B51D4CBC
|
||||
:401940002378DBB2DD0634D518060AD503F00F03012B2ED1FFF74EFF174B1B78190609D538BD5A0602D5FFF7D7FF03E09D0620D5FFF786FF23781B061BD4104B1A78104B10
|
||||
:401980001B7813430F4A13701278934211D10A4A0849154613782078DBB2000605D41378DBB20B700B7803F00F0328788342F1D138BD38BD286000405D86FF1F6E86FF1F8B
|
||||
:4019C000E586FF1F29600040054A00231380054A916819B191680B7092685380704700BFE886FF1F6086FF1F0E4808B503889BB213B9FFF783FE13E00B4B02221A700B4BBC
|
||||
:401A000000221A70FFF7E0FF094AD1799379028843EA012392B2934238BF0380FFF728FE012008BD6086FF1F7286FF1F6E86FF1F00600040084B01221A700F3B9B7C074B8D
|
||||
:401A40001A7B02F00302012A1EBFDA7B82F08002DA7301225A7370470B6000407886FF1F094B02221A700F3B93F82230074B1A7E02F00302012A1EBFDA7E82F08002DA7620
|
||||
:401A800001225A76704700BF0B6000407886FF1F0B4B04221A700F3B93F83230094B93F8242002F00302012A1EBF93F8272082F0800283F82720012283F82520704700BFB6
|
||||
:401AC0000B6000407886FF1F0B4B08221A700F3B93F84230094B93F8302002F00302012A1EBF93F8332082F0800283F83320012283F83120704700BF0B6000407886FF1FD4
|
||||
:401B00007047FFF7DFBC00F0B3BB000070B50446184B88B003AA03F11006154618685968083303C5B3422A46F7D11B782B70FCB12223237001AD032328466370FFF77CFB3D
|
||||
:401B4000002220461146AB5C08AC04EB131414F8144C03F00F03847008AC234413F8143C0132082AC1700371417100F10400EAD108B070BD472F00002DE9F0411A4D012242
|
||||
:401B80002E460C2080274FF0080E184B00FB025C14012344187016499CF805802144B8F1000F07D09CF8044024064CBF887081F802E000E08F7000FB0261CC880132E4B2A3
|
||||
:401BC0009C71CC88092AC4F30724DC71CC88E4B21C71C988C1F307215971D6D1054BFF221A70BDE8F08100BF7886FF1F70600040FC5F00400A600040064B074A1B7802EBAA
|
||||
:401C0000C30253681A7C824286BF03EBC0035869002070476C86FF1F942F00002DE9F84F424B1A78002A7ED01878414D0138C0B2FFF7E2FFA8463F4AC3681478007ADFF856
|
||||
:401C400000C1E4B203EBC0000C2600274FF0010E834268D01A78A24263D11CF80420597891425ED19A7893F8039002F07F0206FB02FA05EB0A01CF7093F802B009F00309EA
|
||||
:401C800081F804B093F803B005F80AB0B3F804A0A1F808A093F902A0BAF1000F0BDAB9F1010F0CBF4FF007094FF00D0981F8059081F801E009E0B9F1010F0CBF4FF0050959
|
||||
:401CC0004FF0090981F805904F704FEA02191A4906FB0282494481F802E0B2F808A0CAF3072A81F800A0B2F808A05FFA8AFA81F801A0B2F806A011495FFA8AFA494481F873
|
||||
:401D000006A0B2F80690C9F3072981F80790B2F806905FFA89F981F80490D288C2F307224A71083394E7BDE8F88F00BF7186FF1F7886FF1F6D86FF1FFC5F00407060004018
|
||||
:401D40005E86FF1F08B5064B18780138C0B2FFF753FF20B143681B7900EBC300406908BD7186FF1F00212DE9F84F0B464E4E0C2707FB01F401313219092933554FF000057F
|
||||
:401D80009370494CD3701381937253705371EFD118B1464B1D70464B1D70464B1A78002A7FD0187801250138C0B2FFF725FFA8464368DFF8F8E0DB790C2713F0400F3E4BA2
|
||||
:401DC0004FF0000C1A7814BF42F0010202F0FE021A70027AD20007FB0541C36803EB02094B4531D093F802A00AF07F06AE4229D10E89B3F804B0B6B25E4538BFA1F808B058
|
||||
:401E00001E7893F801B01EF80660B3451AD181F804A0DE780E7093F902A0DE78BAF1000F06F0030607DA012E0CBF07260D264E7181F8018006E0012E0CBF052609264E7156
|
||||
:401E400081F801C00833CBE70135092DC3D1C1680A328B1C0A440C200833934209D013F8081C13F80A5C01F07F0100FB01418D72F2E7FFF767FF114B0121186000230C2005
|
||||
:401E800000FB0142D3801289013113449BB203F00102134409299BB2F2D1BDE8F84FFFF76BBEBDE8F88F00BF7886FF1F5E86FF1FE686FF1F7186FF1F6F86FF1F7486FF1FB3
|
||||
:401EC000114B1B7903F07F035A1E072A19D80F490C2202FB031291781B0141F0010191700021D170517841F002015170127912F0800F074A1A4414BF8D2389239370FFF7DF
|
||||
:401F000053BC0020704700BF006000407886FF1FFC5F004030B4194B1A7902F07F02531E072B27D8164B0C2404FB02339978154D01F0FE0199700021D97029461201505DEB
|
||||
:401F4000114400F07F0050555A7802F0FD025A701A795B78120605D5012B01D18C7006E00D2303E0012B0CBF082309238B7030BCFFF71ABC002030BC704700BF00600040FD
|
||||
:401F80007886FF1FFC5F004010B50D4B0D4C21791878C9B20138C0B2FFF72EFE43681B798B4201D2012909D8074A0848535CDBB24354A3780120DBB2535410BD002010BDFA
|
||||
:401FC0007186FF1F006000405E86FF1FE686FF1F38B58A4A8A4C13780021DBB221801806517840F18D800A2900F20581DFE811F05D00030103010301030103010B00030117
|
||||
:402000007E0003018200D3787C49012B09D17D4B1A787D4B03EBC2035B685B686360122310E0CB78022B12D18878FFF7E5FD002800F0E180436863606368DA7863689B7836
|
||||
:4020400043EA02232380BDE83840FFF7CDBCCB78032B26D16D4B00228878D5B2854209D3664A91786A4AEE2908BF1346634A917881B106E0187801320028F1D0187803446E
|
||||
:40208000EAE764499278097C914203D16248FFF73DFD614B1A78002A00F0AD801A78228018E0BDE8384000F019BA13F0030313D0022B40F0A0802380504B0C211B7903F0A6
|
||||
:4020C0007F02564B01FB02339A78554BD2B21A7000225A706360B6E702222280514A11784F4AC9B2117053706260ACE7012323804D4BEFE70123238013794C4A1344E9E7A5
|
||||
:4021000001390A2977D8DFE801F037764F76067676760A7620009378454ADBB25AE0937803F0FF0153B9404B1A7891425FD01970404B01201870FFF715FE58E0481EC0B251
|
||||
:40214000FFF75AFD0028EED155E0FFF71DFF002851D02A4A384913791279DBB2D2B20A70364A3249D25CCB5C9A4240D0314B01221A70FFF753FD3AE003F00303012B2BD01F
|
||||
:4021800009D3022B37D11D4B9B78002B33D1BDE83840FFF7BFBE194B9B78012B2BD1214A137803F0FD0315E003F00303012B13D008D3022B1FD1114B9B78E3B9BDE838402F
|
||||
:4021C000FFF77EBE0D4B9B78012B14D1154A137843F0020313700AE0084B1A795AB998781B791749DBB2CA5C22EA0002CA54BDE83840FFF7D9BA002038BD00BF00600040AC
|
||||
:402200006086FF1F6C86FF1F942F0000F82F0000802F00006B300000EA86FF1F7886FF1F5186FF1F6F86FF1F7186FF1F5E86FF1F5C86FF1F7086FF1F6D86FF1FE686FF1FDE
|
||||
:402240007386FF1F074B1A78120609D55B78012B06D1054B054A5A6012781A80FFF7C4BB00207047006000406086FF1F582F0000024B1878C0F38010704700BF8F450040F9
|
||||
:40228000704738B505460078012428B100F0D0F8285D0134E4B2F8E738BD08B50D2000F0C7F8BDE808400A2000F0C2B8014B1870704700BF7C640040014B1878704700BF07
|
||||
:4022C0006A640040014B1870704700BF78650040074A0223136002F688321268E0215064044A11706FF440710A441360704700BF80E100E001E400E073B515461E460B4C41
|
||||
:402300000023019300930A46014618462370FEF747FE324629462078FEF702FE02212078FEF7ECFD207802B070BD00BFF480FF1F064A0123136002F688321268E021106434
|
||||
:40234000034A1170A2F540721360704780E100E000E400E0014B1870704700BF79650040014B1870704700BF7A640040014B1870704700BF7B640040014B1870704700BF94
|
||||
:402380007F640040014B1870704700BF7E64004073B515461E460B4C01230022019200920A46014618462370FEF7FAFD324629462078FEF7B5FD02212078FEF79FFD207867
|
||||
:4023C00002B070BDF580FF1F064A0423136002F688321268E0219064034A1170A2F202321360704780E100E002E400E0014B04221A60704700E100E0014B04221A60704792
|
||||
:4024000080E100E0014B1870704700BF7D6400400230800803D000BF01380046FCD17047EFF3108072B6704780F31088704700BFFEB5494652465B460EB407462449096867
|
||||
:402440008A46244A12682448022100F05FF8030020480068C018204900F058F8143883460121C9430C4601250026FFF7D9FF814651460B7823400B7058460130FFF7C8FF80
|
||||
:402480003800F04028400B78234003430B705846FFF7BEFF0136072EF2D9002001300138013001200B78234003430B7058460430FFF7AEFF4846FFF7B7FF00BF00BF00BFAE
|
||||
:4024C0000EBC894692469B46FEBD00BFAFF30080E880FF1FE480FF1F00C20100094A137803F00303012B0AD0022B09D113790C2103F07F02044B01FB02339B7A00E0137911
|
||||
:4025000000207047006000407886FF1F002902D0B0FBF1F0704708B14FF0FF3000F008B80029F8D00246B0FBF1F000FB11217047704700BF014B1868704700BF5881FF1F9B
|
||||
:402540000E4B70B51E460E4C0025E41AA410A54204D056F8253098470135F8E700F0A2FD084B094C1E46E41AA4100025A54204D056F8253098470135F8E770BDB030000025
|
||||
:40258000B0300000B0300000B830000010B5431E0A44914204D011F8014B03F8014FF8E710BD03460244934202D003F8011BFAE7704730B5141E05469BB0184604DA8B2390
|
||||
:4025C0002B604FF0FF301DE04FF40273ADF80C300CBF234604F1FF33029305934FF6FF7300910491ADF80E3002461E9B6946284600F072F8431CBCBF8B232B6014B1009B19
|
||||
:4026000000221A701BB030BD07B5009313460A46014603480068FFF7CCFF03B05DF804FB5881FF1F2DE9F0478E6882469E420C46914698463ED88A8912F4906F3AD02568CE
|
||||
:40264000096902236F1A656905EB450595FBF3F57B1C43449D4238BF1D4653050FD5294600F040FB064698B13A462169FFF78EFFA38923F4906343F08003A38113E02A46F8
|
||||
:4026800000F08EFB064670B92169504600F0DEFA0C23CAF80030A3894FF0FF3043F04003A381BDE8F08726613E44266046466561ED1BA560464528BF464649463246206858
|
||||
:4026C00000F0A8FAA36800209B1BA36023681E442660BDE8F08700002DE9F04F9DB003938B8980461C060D4616460DD50B695BB9402100F0F7FA2860286118B90C23C8F875
|
||||
:402700000030CDE040236B610023099320238DF82930DFF89CB130238DF82A3037463C4614F8013B1BB9B7EB060910D003E0252BF9D02746F3E74B46324629464046FFF774
|
||||
:4027400071FF013000F0A780099B4B4409933B78002B00F0A08000234FF0FF3204930793059206938DF853301A930126052221784E4800F041FA671C049B38B14B4A3C4671
|
||||
:40278000801A06FA00F018430490EFE7D90644BF20228DF853201A0744BF2B228DF8532022782A2A03D0079A00210A200BE0039A111D12680391002A10DA524243F00200F7
|
||||
:4027C000079204900BE027463B780134303B092B03D800FB02320121F5E701B107923B782E2B1ED17B782A2B0AD1039B02371A1D1B680392002BB8BF4FF0FF33059310E09B
|
||||
:40280000002319460593781C0A2407463A780130303A092A03D804FB01210123F5E703B1059103223978224800F0E6F940B14023CBEB000003FA00F0049B013718430490DD
|
||||
:40284000397806221B487E1C8DF8281000F0D4F988B1194B33B9039B073323F007030833039314E003AB00932A46144B04A94046AFF3008007E003AB00932A460F4B04A9C1
|
||||
:40288000404600F093F8B0F1FF3F824603D0099B5344099342E7AB895B0601D4099801E04FF0FF301DB0BDE8F08F00BF7F300000853000008930000000000000252600002B
|
||||
:4028C0002DE9F04791461F460A698B6806469342B8BF1346C9F8003091F843200C46DDF8208012B10133C9F800302368990642BFD9F800300233C9F80030256815F006057D
|
||||
:4029000010D104F1190A07E00123524639463046C04701301AD00135E368D9F800209B1A9D42F1DB94F843302268003318BF012392060FD5E118302081F843005A1C94F8D8
|
||||
:4029400045102244023382F8431003E04FF0FF30BDE8F08704F1430239463046C0470130F4D02268D9F80050E36802F00602042A08BF5D1B2269A3680CBF25EAE5750025B6
|
||||
:402980009342C4BF9B1AED184FF000091A344D4509D00123224639463046C0470130D5D009F10109F3E70020BDE8F0872DE9F04317460A7E85B06E2A984606460C460C9B6E
|
||||
:4029C00001F1430E00F0AE8011D8632A22D009D8002A00F0BB80582A40F0CA8081F84520834955E0642A1ED0692A1CD0C0E0732A00F0B08009D86F2A2ED0702A40F0B8802B
|
||||
:402A00000A6842F020020A603EE0752A24D0782A3AD0ADE01A6801F14205111D1960136884F84230A8E021681A6811F0800F02D0111D196008E011F0400F02F1040119606C
|
||||
:402A400002D0B2F9003000E01368002B3CDA2D225B4284F8432037E021681A6811F0800F02D0111D196007E011F0400F02F10401196001D0138800E01368227E5C496F2ACA
|
||||
:402A800014BF0A2208221BE078225A4984F845202268186812F0800F00F104051D6003D1550601D5038800E00368D00744BF42F0200222601BB9226822F0200222601022F1
|
||||
:402AC000002084F8430001E049490A226568002DA56008DB206820F0040020602BB9002D7DD175460CE0002B79D07546B3FBF2F002FB1033CB5C05F8013D03460028F5D1BC
|
||||
:402B0000082A0BD12368DA0708D5236962689A42DEBF302305F8013C05F1FF35C5EB0E0323612EE008681A6810F0800F496903D0101D1860136808E010F0400F02F1040011
|
||||
:402B40001860136801D0198000E0196000232361754616E01A68111D1960156800216268284600F049F808B1401B6060636804E004F1420584F8422001232361002384F833
|
||||
:402B80004330CDF800803B4603AA21463046FFF797FE013002D14FF0FF3026E023692A4639463046C0470130F5D023689B0710D5002504F1190907E001234A463946304683
|
||||
:402BC000C0470130E7D00135E368039A9B1A9D42F2DBE068039B9842B8BF184605E00B7804F1420584F842308AE705B0BDE8F083472F00009030000010B5C9B20244904274
|
||||
:402C0000034605D01C7801308C42F8D1184610BD002010BD884210B501EB020301D8421E0BE09842FBD28118D21AD34204D013F8014D01F8014DF8E710BD994204D011F845
|
||||
:402C4000014B02F8014FF8E710BD000038B50546002944D051F8043C0C1F002BB8BFE41800F0D4F81E4A1368114613B96360146030E0A3420DD92268A018834201BF186830
|
||||
:402C80005B681218226063600C6023E0A24203D813465A68002AF9D118681918A1420BD12168014458188242196013D110685268014419605A600DE002D90C232B6009E0C1
|
||||
:402CC00021686018824201BF106852680918216062605C602846BDE8384000F098B838BD5886FF1F70B5CD1C25F0030508350C2D38BF0C25002D064601DBA94202D90C232E
|
||||
:402D0000336046E000F082F8234B1C681A462146A1B10B685B1B0ED40B2B03D90B60CC18CD501EE08C420BBF63684B681360636018BF0C4615E00C464968E9E7174C2368F3
|
||||
:402D40001BB9304600F052F820602946304600F04DF8431C18D0C41C24F00304A0420DD12560304600F053F804F10B00231D20F00700C31A0ED05A42E25070BD211A30463F
|
||||
:402D800000F034F80130EBD10C233360304600F03EF8002070BD00BF5886FF1F5486FF1FF8B5074615460E4621B91146BDE8F840FFF798BF1AB9FFF749FF2846F8BD00F084
|
||||
:402DC00027F885420ED929463846FFF78BFF044650B131462A46FFF7D9FB31463846FFF735FF01E03046F8BD2046F8BD38B5064C0023054608462360FDF7B8FF431C02D1FC
|
||||
:402E0000236803B12B6038BD0C87FF1F7047704751F8040C0028BEBF091851F8043CC0180438704700000000050209020B020D020F02110213027265706C79203078253091
|
||||
:402E4000327800686F6D696E6700626567696E6E696E67207365656B2066726F6D20256420746F20256400756E65787065637465646C7920646574656374656420747261A1
|
||||
:402E8000636B20300066696E6973686564207365656B0057616974696E6720666F72205553422E2E2E0055534220726561647900636F6D6D616E64203078253032780077D8
|
||||
:402EC00061697400756E64657272756E206166746572202564207061636B65747300636F756E743D256420693D256420643D2564207A7A3D25640073746172742065726153
|
||||
:402F000073696E670073746F702065726173696E670069646C650000510040100030510040400000000140800A000B0140000500140140000800400140000A004C01400040
|
||||
:402F400002005001402000303132333435363738394142434445460028000000000104000100000000000000000157494E5553420000303030303100000000000000000004
|
||||
:402F800012034D0053004600540031003000300001000000010000009C2F0000010000006B300000000000000000000001000000B42F0000010000003D3000000400000072
|
||||
:402FC000D62F0000000000000000000000000000D42F0000FF00000001024000FF00000082024000FF00000003034000FF00000084034000FF000203040309041603460042
|
||||
:403000006C007500780045006E00670069006E0065002A0343006F0077006C00610072006B00200054006500630068006E006F006C006F0067006900650073000009022EA4
|
||||
:403040000001010080320904000004FF00000007050102400000070582024000000705030340000A0705840340000A12010002FF0001080912006E010002018001430023A3
|
||||
:403080002D302B2000686C4C00656667454647003031323334353637383961626364656600000000F8B500BFF8BC08BC9E46704759000000E90D0000F8B500BFF8BC08BC30
|
||||
:4030C0009E46704735000000D8300000C880FF1F98000000B0050000000000001087FF1F7F800000030000000000007D00FA0000400000000090D0031550004002000000CD
|
||||
:4031000005000000FFFF000000000000000000000000000000000000000000000000000000000000000000007D3000000000000000000000000000000000000000000000DF
|
||||
:4031400000000000000000000000000000000000000000000000000000000000000000000000000000000000F880FF1F0000000000000000000000000000000000000000B9
|
||||
:40318000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F
|
||||
:4031C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000CF
|
||||
:40320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008E
|
||||
:40324000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004E
|
||||
:40328000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000E
|
||||
:4032C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000CE
|
||||
:40330000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008D
|
||||
:40334000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004D
|
||||
:40338000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000D
|
||||
:4033C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000CD
|
||||
:40340000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008C
|
||||
:40344000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004C
|
||||
:40348000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C
|
||||
:4034C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000CC
|
||||
:40350000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008B
|
||||
:40354000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004B
|
||||
:40358000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B
|
||||
:4035C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000CB
|
||||
:40360000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008A
|
||||
:40364000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004A
|
||||
:40368000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000A
|
||||
:4036C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000CA
|
||||
:403700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000089
|
||||
:403740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000049
|
||||
:403780000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009
|
||||
:4037C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C9
|
||||
:403800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000088
|
||||
:403840000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000048
|
||||
:403880000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008
|
||||
:4038C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C8
|
||||
:403900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000087
|
||||
:403940000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000047
|
||||
:403980000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007
|
||||
:4039C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C7
|
||||
:403A00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000086
|
||||
:403A40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046
|
||||
:403A80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006
|
||||
:403AC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C6
|
||||
:403B00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000085
|
||||
:403B40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045
|
||||
:403B80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005
|
||||
:403BC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C5
|
||||
:403C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000084
|
||||
:403C40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044
|
||||
:403C80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004
|
||||
:403CC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C4
|
||||
:403D00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083
|
||||
:403D40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000043
|
||||
:403D80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003
|
||||
:403DC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C3
|
||||
:403E00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082
|
||||
:403E40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000042
|
||||
:403E80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002
|
||||
:4000000000800020110000006112000061120000064A08B5136843F020031360044B1A6803F53F5302331A6001F038F9E8460040FA46004010B5054C237833B9044B13B10E
|
||||
:400040000448AFF300800123237010BD6881FF1F00000000E03A0000084B10B51BB108490848AFF300800848036803B910BD074B002BFBD0BDE81040184700BF0000000027
|
||||
:400080006C81FF1FE03A0000C880FF1F000000000A4A0B4B116801310B40002BBEBF03F1FF3363F03F030133136011685368994202BF024B01221A72704700BF8881FF1FA2
|
||||
:4000C0003F0000800A4A0B4B516801310B40002BBEBF03F1FF3363F03F030133536051681368994202BF024B01221A72704700BF8881FF1F3F000080024B012200205A7293
|
||||
:4001000002F072BA8881FF1F10B5C4B2204601F087FA0128FAD110BD08B572B60F4B0F49DA680132DA601A690132C82A08BF00221A615A6918690132A72A08BF00224A6178
|
||||
:400140005B69002B0CBF02230023002814BF184643F0010002F0B0FF62B608BD8881FF1F38B50446C5B2284602F0E0F9062002F0FDFB44F00200C0B202F0D8F9062002F0D1
|
||||
:40018000F5FB284602F0D2F9BDE83840062002F0D7BB10B5642402F0C3F930B90120FFF7DFFF013CF7D1204610BD012010BD70B5C4B220460E4601F03BFA314605460246D9
|
||||
:4001C000204601F0F7FA204601F02AFA0128FAD0284670BD38B5044D0024285D013402F075FB402CF9D138BDA081FF1F08B502F08FFD002002F098FD02F0AAFD02F0B4FDA8
|
||||
:4002000080B208BD10B50446012002F0A7F9642002F096FBFFF7EAFF2080002002F09EF9642002F08DFBFFF7E1FF608010BD08B502F09AFE002002F0A3FE02F0B5FE02F0C4
|
||||
:40024000BFFE80B208BD10B50446FFF7A2FF322002F076FBFFF7EBFF20800020FFF780FF322002F06DFBFFF7E2FF608010BD0FB400B593B014AB53F8042B402102A8019397
|
||||
:4002800003F016F802A802F0B6F902F0C0F913B05DF804EB04B0704710B5044601780648FFF7E5FF0420FFF72FFF62782146BDE81040042001F00CBAF43A000007B50023BF
|
||||
:4002C000ADF804308DF80600032301A88DF80530FFF7E2FF03B05DF804FB000010B5074C94F8583043B1002002F014F9002002F0A7FE002384F8583010BD00BF8881FF1F63
|
||||
:4003000038B5104D837895F85B2004469A4204D0FFF7E4FF002385F85E302368C5F859302279094B1A71A378002B14BF0220012002F086FEE07802F07DFE2079BDE83840D7
|
||||
:4003400002F0B4BE8881FF1FE181FF1F38B50D4C94F8585065B904F15900FFF7D1FF012002F0D8F84FF47A7002F0EAFA84F85E50E3682366012384F85830BDE8384002F0AB
|
||||
:400380001DBB00BF8881FF1FF8B51E4C0646FFF7DDFF94F85E3003B15EB91B48FFF767FFFFF7F7FE0120002384F85E00636602F0DDFA3246616E1548FFF759FF114D002794
|
||||
:4003C000636E9E4216D002F0ABF800B16F66636E9E4205DD0020FFF7C3FE6B6E013305E005DA0120FFF7BCFE6B6E013B6B6602F0E5FAE5E7322002F0A3FABDE8F8400448B2
|
||||
:40040000FFF735BF8881FF1F013B0000083B0000253B00002DE9F04F9BB062B602F038FB9B49042002F05CFB9A4802F085F89A4802F028FE994802F0B9F802F009FD02F0E5
|
||||
:40044000DBFB002002F0FCFD02F0D4F80221002001F09CF803210846914C02F08FFA002384F85B30FFF772FFFFF793FE84F86800FFF734FF012384F85B30FFF767FFFFF7A9
|
||||
:4004800088FE84F86900FFF729FF94F86800854B854994F869202546002A14BF0A461A46002808BF19468148FFF7E1FEA24602F085FA94F8583043B12A6EEB689B1A41F2D4
|
||||
:4004C0008832934201D9FFF709FF01F097F818B97748FFF7CCFE04E001F096F80028F7D109E001F08BF80028FBD07248FFF7BFFE032001F0B3F9032001F092F80128D6D187
|
||||
:400500006D48FFF7FDFE6D490320FFF750FE94F86A106B48FFF7ABFE94F86A30023B142B00F27684DFE813F0150074041E00740424007404480074046B007404D800740496
|
||||
:40054000FE017404AC037404CC037404D3037404ED0303238DF828308DF829300C238DF82A30CAE394F86C00FFF70EFF554BC1E3FFF7ECFE00236372E068627A02F0FF018F
|
||||
:4005800032B9EB681B1AB3F57A7FF6DD0B460AE04BB100228AF80920DAF80C10627A12B9EB685B1AFAE707228DF8282004228DF82920ADF82A30A0E30220FFF7A5FD0027C5
|
||||
:4005C0000DF1280902F0FAF94FF480780026C8EB07039A1906F809200136402EF9D10220FFF792FD32464946022001F071F8B8F10108EBD10137402FE4D1334B42E04FF0AD
|
||||
:400600000109002702F0DAF94FF00008012001F025F9012001F004F80128FAD10DF1280B4022594601F0C6F8012000F0F9FF0028FAD1064608EB07030593059B1BF80620B4
|
||||
:400640003344DBB2934209D08DE80C003946334642461E48FFF70BFE4FF000090136402EEBD108F10108B8F5807FCFD10137402FC8D149461648FFF7FAFDB9F1000F00F0A8
|
||||
:400680005981144B1B8809A8ADF8243036E300BF19010000F900000091000000C50000008881FF1F373B0000333B00003A3B0000523B0000653B0000E181FF1FF281FF1FB9
|
||||
:4006C0006F3B0000E43A0000E63A00007E3B00009A3B0000E83A000094F86C0001F03EFF606EFFF751FE02F04FFD934B934F1A78002602F0FB021A701A7842F001021A70A9
|
||||
:400700001A7802F0FE021A701A7802F0FE021A7002F03EFD0220FFF7F7FC41F6FF734FF480420121022002F091FC84F8AA0002F0B3F8B8550136402EF9D1DFF82082002616
|
||||
:4007400008F1990B1FFA8BF70136402E14BF3246002218F8010F22440623127E402102F0CFF83A4646F2434198F8000002F0DAF84037402EBFB2E7D19AF86D3043B10023F2
|
||||
:400780008AF80930637A002BFCD000238AF80930182200210AA802F057FD694B4FF0FF320C9340230D930023236062602372236894F8AA002344197E02F026F894F8AA00B1
|
||||
:4007C00001F0E4FF012194F8AA0001F0B7FF2368002BFCD000239946CAF80430DAF80C200127059202F0EAF8059AE3689B1AB4F86E2093420ED36FB1042195F8AA0002F01E
|
||||
:400800000FF894F8AA0002F01BF80028F9D107468AF80800237A03F0FF08002B48D16A682B689A4202D1002FDCD141E063680AA80BEB831343440A93C8F140030B9300F00A
|
||||
:4008400001FB0B9B09F10109C3F1400398440D9B5FFA88F8E3B93B4E0220FFF755FCA6F1400EBEE80F000FC6BEE80F000FC6BEE80F000FC69EE80F0086E80F00A6F1300193
|
||||
:400880004022022000F024FF703E40230C960D93B8F13F0FCAD962682B4B01321340002BBEBF03F1FF3363F03F030133636099E70AA8267A00F01CFB0220FFF725FC0D9BDA
|
||||
:4008C000F6B2402B07D0022040221E4900F000FF0220FFF719FC0D9B022033F040021DBFC3F1400292B21749114600F0F1FE0220FFF70AFCFFF76EFC36B11448FFF7B7FCC2
|
||||
:400900000220FFF7DBFC06E0114B09A81B88ADF82430FFF7C1FC627A4946237A0D48FFF7A6FC78E20C48FFF7A2FCD4F86E6016F03F0615D003206CE293640040A081FF1F9E
|
||||
:400940003892FF1F7892FF1F3F000080A43B0000EA3A0000BE3B0000D13B00009F81FF1F012001F001FE95F86C0001F0F7FD02F00BFCB94BB94F1A7842F004021A701A7888
|
||||
:4009800042F001021A701A7802F0FE021A701A7802F0FE021A7002F0FBFB686EFFF7F4FC01214FF4804341F6FF72084601F0E2FD85F8AA0001F070FFB8550136402EF9D1C7
|
||||
:4009C000DFF8B882002708F199039EB207930137402F14BF3A46002218F8010F22440523127E402101F08CFF314646F2475298F8000001F097FF4036402FB6B2E7D1DAF8D3
|
||||
:400A00006E3000269B09182231464FF0FF3B0AA8CAF800600593CAF804B0B1468AF80860B04602F011FC0D973746012000F016FF069601F0C3FFB8F1000F0AD14EB901201B
|
||||
:400A400000F0EEFD012804D14022854900F0B2FE06462268834B01321340002BBCBF03F1FF3363F03F036168B8BF01338B4200F09080069B3BB1237A002B40F09B806B7A7C
|
||||
:400A8000002B40F097800B9BBBBBB8F1000F09D0754A7F2199540133402BFBD1724A0B930A922AE04EB3012000F0BAFD28BBDFF8B8E13F2E0EF1400CBCE80F00AEE80F0034
|
||||
:400AC000BCE80F00AEE80F00BCE80F00AEE80F009CE80F008EE80F00AEF130030A9307F101070B9607DD059BBB4204D0012000F0B5FE464601E04FF001080B9BDBB1236893
|
||||
:400B0000079A0AA802EB83120D9BC3F1400313440C9300F0FCF90D9B6BB92A68514B01321340002BBEBF03F1FF3363F03F030133236040230D93636801332AD12B683F2BD2
|
||||
:400B400027D14FF0000BC5F804B001F041FD85F808B06B6895F8AA002B44197E01F054FE95F8AA0001F012FE012195F8AA0001F0E5FD85F809B0637A002BFCD04FF0000B53
|
||||
:400B800001208AF809B001F02FFD584601F0ECFC01E0069B2BB1237A63B96B7A53B90123069363685B453FF444AF09F10109D5F804B03EE761682D482268FFF758FB01F043
|
||||
:400BC0000DFD012001F0D0FC002001F00DFD042194F8AA0001F024FE94F8AA0001F030FE0028F9D19AF8AA0001F0BEFD9AF809309AF808200293012303920193CDF80080A9
|
||||
:400C00004B463A4605991A48FFF731FBB8F1000F16D1059BBB420AD0012000F001FD01280646F6D10E49FFF7C2FA3F2803DC012000F028FE04E0304600F010FE0137E8E73B
|
||||
:400C4000FFF7C8FA0B48FFF712FB237A0BB10220DFE0094B16E500BF97650040A081FF1F7892FF1F3F0000803892FF1FDB3B0000E63B0000163C0000EC3A00009F81FF1FE7
|
||||
:400C800094F86C0001F06AFC606EFFF77DFB6648FFF7EDFA00236372637A002BFCD0012001F0A2FC00238AF80930637A002BFCD0002001F099FC5D48FFF7D9FA5C4B19E03C
|
||||
:400CC000002084F85E00FFF75FFB5A4B12E094F8683023B195F869200AB985F86C2094F869201AB113B9012385F86C305248FFF707FB524B1B88ADF828300AA8FFF7CCFA13
|
||||
:400D000089E0FFF7EBFA02F021F9002002F0C4F82A2601F0EFFF002001F092FF324600210AA802F091FA17238DF828308DF8296001F044FE002001F0EDFB002002F080F920
|
||||
:400D4000C82001F0FDFD0DEB0600FFF75BFA0DF13E00FFF778FA01F031FE012002F070F9322001F0EDFD0DF12E00FFF74BFA0DF14200FFF768FA012001F0CCFB4FF49670C9
|
||||
:400D800001F0DEFD01F01AFE0DF13600FFF73AFA0DF14A00FFF757FA002001F0BBFB4FF4967001F0CDFD01F009FE022002F048F9322001F0C5FD0DF13200FFF723FA0DF113
|
||||
:400DC0004600FFF740FA012001F0A4FB4FF4967001F0B6FD01F0F2FD0DF13A00FFF712FA0DF14E00FFF72FFA002001F093FB4FF4967001F0A5FD01F0E1FD002002F020F9E5
|
||||
:400E0000002384F85E3002F023F801F0F5FE74E70120FFF753FA032000F020FD0848FFF726FAFFF744BB00BF253C0000333C0000EE3A0000F03A0000F281FF1FF23A0000AC
|
||||
:400E4000403C000070B5002401254268002A4ED0C368002B4BD00368013A591C01601B784260802B01D145752FE013F0800F467D0269017D12D036B1D20042F004020331E8
|
||||
:400E8000026101754475026903F00103D20042F004021A43037D0261033315E046B13F2B06D9D20042F004020331026101754475026943EA0223427D036112B143F0C00320
|
||||
:400EC0000361037D447508330375037D072BBCD90269083B22FA03F38268511C81601370C368013BC360037D083B0375ADE770BD07B5027D42B102AA002102F8011D0260E5
|
||||
:400F000001224260FFF79EFF03B05DF804FBF0B5012100244368002B43D0C268002A40D0427D4AB183685A1C8260827D1A70C3684475013BC360EDE7027D072A0BD806687C
|
||||
:400F40000769751C05603578013B45EA07250832056143600275027D0369A2F10805EB40DBB203F0C006802E07D0C02E0ED103F03F0383754175802308E0C3F3401363F0F5
|
||||
:400F80007F03033A03F08103027502E00575002BC0D08268551C85601370C368013BC360B8E7F0BD2DE9F04172B6884B61221A70A3F5F06301221A801924854A9C7092E84B
|
||||
:400FC00003008033062283F8002283E80300522203F580731A707F4B7F4A1B787F4EDBB2137040F618027E4B00251A8041F2512223F8022C33784FF4F07003F0010343EAE3
|
||||
:40100000450502F0B9F8013C05F003052ED0032DF0D1744B4FF480721A8007221A70724A002548211570917002221D705D7103F8032C0422DA716D4A6D4C13786D4E43F086
|
||||
:401040000103137012F8013C062743F0030302F8013C2378012243F0800323705B4B1A70654A137843F02003137000E0FEE707FB056300219A881868013502F0E5F8072D90
|
||||
:40108000F5D15E485E4E002550F8041F05F1105303F1520221F0FF075333C9B20B4452005B0002329A4206D012F802EC12F801CC0EF807C0F5E7B0420D44E5D1514A0023BE
|
||||
:4010C00013609360136193614F4B504F1A68504BDFF888811A604F4B1A684F4B1A604F4A137843F002031370137C43F0020313742378A2F5863243F040032370413A13781C
|
||||
:4011000043F010031370464A464B07CA03C31A80454A2833106843F8250C127903F8212C424A07CA03C31A80414AE83B07CA03C31A80404A083307CA03C31A803E4A3F4B4F
|
||||
:40114000A2F5616203CBC2F8100EC2F8141E1378042043F008031370394B02F5AA521B783D78DBB298F80060EDB203F007010C321B091170F6B2537045F003033B7046F0D3
|
||||
:40118000030388F800302F4B48221A702E4A402313702E49937013729372082382F81F3220220A7048710A72294A0A20137001F0DDFB284B88F8006044223D70264D1A7076
|
||||
:4011C00094E80F0007C52B80BDE8F081004800404C0F00480F010049A146004025420040224200400440004006400040A2430040A0430040453C0000E8460040FCFFFF475F
|
||||
:40120000A000004800760040540F0048F846004020760040580F004828760040035001400C0F0048C0510040180F0048200F00482C0F0048380F004832510040440F0048E6
|
||||
:40124000CF0100491D51004001590040235B0040585B004076580040B0430040F946004008B501F0C5FF03680C2B00D1FEE7FEE7084908B50B68084A1844821A802A01DC9B
|
||||
:40128000086005E001F0B4FF0C2303604FF0FF33184608BDCC80FF1FC893FF1F80B51148114B0025C0B1A3F1100192C922460439161BB74204D051F8046F42F8046BF7E7CE
|
||||
:4012C000114653F8046C8C1AA64202D041F8045BF9E701381033E5E701F090FFFFF79AF8FEE700BF01000000143E0000124A134B10B51A60124A134C1368134843F4007389
|
||||
:4013000013600023032B98BF54F823204FEA830188BF0E4A0133302B4250F3D10C4B1A780C4B1A700C4B084A1A60FFF73BFEBDE8104001F0EDB900BF0004FA050CED00E07F
|
||||
:4013400014ED00E0000000000080FF1F61120000BC760040C080FF1F08ED00E0F8B501F013FF4B4A01271378022643F001031370137C484C43F001031374474B02F5E3525D
|
||||
:401380001F700B3203F8946C1378054603F07F031370002001F0EAFA2378404A03F0F90323701378384603F0DF03137023783B43237001F0DBFA282001F0D8FA384B304625
|
||||
:4013C0001A7802F07F021A701A7802F0BF021A7023783343237001F0C9FA2378314A43F0040323700023137053702F4AFF2199540133092BFBD1284601F0CAFE07211720AB
|
||||
:4014000001F0FCFA2949172001F0EAFA0721182001F0F4FA2649182001F0E2FA0721152001F0ECFA2349152001F0DAFA0721052001F0E4FA2049052001F0D2FA0721062045
|
||||
:4014400001F0DCFA1D49062001F0CAFA0721084601F0D4FA1A49072001F0C2FA0721082001F0CCFA1749082001F0BAFA0021162001F0C4FA1449162001F0B2FA07210C203A
|
||||
:4014800001F0BCFABDE8F84010490C2001F0A8BAA5430040944300409D60004012600040F851004084600040ED92FF1F2B1D0000651B0000291D00005D1C0000891C00002C
|
||||
:4014C000B91C0000F11C0000311D0000A51D0000214B224A10B5187000231370204A40201370204A0F2413701F4A13701F4A13701F4A13701F4A13701F4B4FF400021A60E9
|
||||
:401500004FF080721A604FF400121A6020221A601860802018604FF480701860174804704FF480001860164B1A70933B19B91A7802F0FE0202E01A7842F001021A70114B8E
|
||||
:4015400003221A70802203F8202C012001F014FE0D4B04221A7010BD0893FF1F0E93FF1F0C93FF1F0D93FF1F0993FF1FF892FF1F0B93FF1F8093FF1F00E100E09E60004099
|
||||
:401580009C600040286000401260004070B5074C054623780E461BB9FFF7E0FE0123237031462846BDE87040FFF792BFB892FF1F0A4A002313700A4A13700A4A13700A4A7F
|
||||
:4015C00013700A4A13700A4A13700A4A13700A4B03221A70802203F8202C70470E93FF1F0C93FF1F0D93FF1F0993FF1FF892FF1F0B93FF1F8093FF1F28600040014B187812
|
||||
:40160000704700BF0D93FF1F044B1A7802F0FF001AB118780022C0B21A7070470C93FF1F024A0C2303FB0020407870471493FF1F431E072B0CD8074A064B00010344805CAD
|
||||
:401640005B7800F00F0043EA0020023880B2704700207047FC5F00401A4A38B50C2303FB00231B79090C13F0800F00F1FF35044619BF8AB24FF480438BB24FF48042032DDF
|
||||
:4016800018D8DFE805F002070C110021084601F01BF80DE00021084600F0FAFF08E00021084600F0D9FF03E00021084600F0B8FF054B1855EDB2072D03D801F0EDF8034BF9
|
||||
:4016C000185538BD1493FF1FE492FF1FED92FF1F431E072B2DE9F0470446894615465CD82F4F0C2202FB0072D388DFF8B8A09BB2C3F500739D424FF00C0303FB007388BF08
|
||||
:40170000D588DB7884BFC5F50075ADB2254A43EA15230601B354B244EBB28AF80130224B1A5C9846FF2A01D1FFF796FF0C2303FB047200215170B9F1000F28D03DB31B4F29
|
||||
:40174000385D01F011F811232946FE2218F8040001F0D6F806F5C04278321FFA89F118F8040001F0DFF8124D18F80410385D01F04BF80121385D00F0E1FF735D43F0020353
|
||||
:401780007355735D03F0FD037355BDE8F08703FB04746379DBB28AF80230BDE8F08700BF1493FF1FFC5F0040ED92FF1FE492FF1F706000402DE9F0470446154688460029C2
|
||||
:4017C00040D0431E072B3FD8FFF732FFA84203D22046FFF72DFF05461D4E335DFF2B03D141462046FFF738FFDFF868A027011AF8040000F0B9FF1223FE222946305D01F05C
|
||||
:401800007FF807F5C0411FFA88F27831305D01F089F8DFF84490315D1AF8040000F0F4FF01211AF8040000F089FF17F8093043F0020307F8093017F8093003F0FD0307F825
|
||||
:40184000093002E00D4600E000252846BDE8F087ED92FF1FE492FF1F70600040431E072B0AD8064A0C2303FB002300225A705A79034BD2B200011A54704700BF1493FF1FDA
|
||||
:40188000FE5F0040431E072B9FBF024B000108221A547047FE5F004030B51A4A1A491B4D0878138803449BB21380194A00231488D8B2A4B27CB1082B0CD050680078C0B22A
|
||||
:4018C000E85450680133013050601088013880B21080ECE718460B780E4C082B0E4A00D040B10E4D2B7883F080032B700F232370022301E0022323701370094B1870087009
|
||||
:4019000030BD00BF8493FF1F8093FF1F00600040FC92FF1FF992FF1F0E93FF1F0A93FF1F8193FF1F074B02221A70074B80221A70064B0F221A70064A00231370054A012004
|
||||
:40194000137070470E93FF1F0A93FF1FF992FF1F8093FF1F8193FF1F30B5164B16491B780A8803F00F03023BDBB21A4492B20A80124C134A0020118889B279B173B1556828
|
||||
:40198000215C013BC9B229705168DBB20131516011880130013989B21180ECE7094A1370094A137883F080031370084B0B221A7030BD00BF296000408493FF1F006000400D
|
||||
:4019C000FC92FF1F8193FF1F0A93FF1FF992FF1F064A06231370064A01201370054B80221A70054B00221A70704700BF0E93FF1FF992FF1F0A93FF1F8193FF1F054B9A6820
|
||||
:401A00003AB19A68044910709A680988518000229A607047FC92FF1F8493FF1F08B5124B1A78D2B21A701B78DBB21A0602D50F4A137008BD0220FFF7E1FF0D4B1B7803F08C
|
||||
:401A40006003202B05D0402B06D043B900F012FC04E001F0A1FB01E000F046FD10B9034B03221A7008BD00BF28600040F992FF1F0060004008B5084A084B01201978138819
|
||||
:401A80000B449BB21380064B00221A70FFF7B6FF044B03221A7008BD8493FF1F8093FF1F0E93FF1FF992FF1F08B50C4B1B78DBB2042B07D0062B09D0022B0DD1BDE8084082
|
||||
:401AC000FFF7D8BFBDE80840FFF746BF0320FFF795FF034B03221A7008BD00BF0E93FF1FF992FF1F08B5054B002201201A70FFF785FF034B03221A7008BD00BF0E93FF1F47
|
||||
:401B0000F992FF1F08B50A4B1A7832B11A78094942F080020A7000221A70074B002201201A70FFF76BFF054B03221A7008BD00BFF892FF1F086000400E93FF1FF992FF1FFD
|
||||
:401B4000074B1B78DBB2042B05D0062B05D0022B05D1FFF7A1BEFFF7C5BFFFF7D3BF70470E93FF1F38B51D4C2378DBB2DD0634D518060AD503F00F03012B2ED1FFF74EFF3F
|
||||
:401B8000174B1B78190609D538BD5A0602D5FFF7D7FF03E09D0620D5FFF786FF23781B061BD4104B1A78104B1B7813430F4A13701278934211D10A4A084915461378207829
|
||||
:401BC000DBB2000605D41378DBB20B700B7803F00F0328788342F1D138BD38BD28600040F992FF1F0A93FF1F8193FF1F29600040054A00231380054A916819B191680B709B
|
||||
:401C000092685380704700BF8493FF1FFC92FF1F0E4808B503889BB213B9FFF783FE13E00B4B02221A700B4B00221A70FFF7E0FF094AD1799379028843EA012392B29342E7
|
||||
:401C400038BF0380FFF728FE012008BDFC92FF1F0E93FF1F0A93FF1F00600040084B01221A700F3B9B7C074B1A7B02F00302012A1EBFDA7B82F08002DA7301225A7370479E
|
||||
:401C80000B6000401493FF1F094B02221A700F3B93F82230074B1A7E02F00302012A1EBFDA7E82F08002DA7601225A76704700BF0B6000401493FF1F0B4B04221A700F3BDD
|
||||
:401CC00093F83230094B93F8242002F00302012A1EBF93F8272082F0800283F82720012283F82520704700BF0B6000401493FF1F0B4B08221A700F3B93F84230094B93F854
|
||||
:401D0000302002F00302012A1EBF93F8332082F0800283F83320012283F83120704700BF0B6000401493FF1F7047FFF741BC0000F0B5184B184E19780C27C9B201234FF025
|
||||
:401D4000000C31B3CA0720D5144A4FEA031E7244947850782040C5070DD507FB03652C79240608D5147804F0FE0414706D790C4CEDB204F80E50840706D507FB036425799D
|
||||
:401D80002D0658BF84F801C090700133DBB24908D7E7F0BD9F6000401493FF1F70600040FE5F004000F0ACBC70B50446184B88B003AA03F11006154618685968083303C5B6
|
||||
:401DC000B3422A46F7D11B782B70FCB12223237001AD03232846637000F08AFE002220461146AB5C08AC04EB131414F8144C03F00F03847008AC234413F8143C0132082A86
|
||||
:401E0000C1700371417100F10400EAD108B070BD6F3C00002DE9F0431C4D01222E460C201F274FF0800E4FF0080C194B00FB02581401234418705F70164998F805902144BB
|
||||
:401E4000B9F1000F07D098F8044024064CBF887081F802C001E081F802E000FB0261CC880132E4B29C71CC88092AC4F30724DC71CC88E4B21C71C988C1F307215971D4D109
|
||||
:401E8000054BFF221A70BDE8F08300BF1493FF1F70600040FC5F00400A600040064B074A1B7802EBC30253681A7C824286BF03EBC0035869002070470893FF1FD03C0000E7
|
||||
:401EC0002DE9F84F424B1A78002A7ED01878414D0138C0B2FFF7E2FFA8463F4AC3681478007ADFF800C1E4B203EBC0000C2600274FF0010E834268D01A78A24263D11CF868
|
||||
:401F00000420597891425ED19A7893F8039002F07F0206FB02FA05EB0A01CF7093F802B009F0030981F804B093F803B005F80AB0B3F804A0A1F808A093F902A0BAF1000FF4
|
||||
:401F40000BDAB9F1010F0CBF4FF007094FF00D0981F8059081F801E009E0B9F1010F0CBF4FF005094FF0090981F805904F704FEA02191A4906FB0282494481F802E0B2F844
|
||||
:401F800008A0CAF3072A81F800A0B2F808A05FFA8AFA81F801A0B2F806A011495FFA8AFA494481F806A0B2F80690C9F3072981F80790B2F806905FFA89F981F80490D28838
|
||||
:401FC000C2F307224A71083394E7BDE8F88F00BF0D93FF1F1493FF1F0993FF1FFC5F004070600040FA92FF1F08B5064B18780138C0B2FFF753FF20B143681B7900EBC300C6
|
||||
:40200000406908BD0D93FF1F00212DE9F84F0B464E4E0C2707FB01F401313219092933554FF000059370494CD3701381937253705371EFD118B1464B1D70464B1D70464B13
|
||||
:402040001A78002A7FD0187801250138C0B2FFF725FFA8464368DFF8F8E0DB790C2713F0400F3E4B4FF0000C1A7814BF42F0010202F0FE021A70027AD20007FB0541C3680E
|
||||
:4020800003EB02094B4531D093F802A00AF07F06AE4229D10E89B3F804B0B6B25E4538BFA1F808B01E7893F801B01EF80660B3451AD181F804A0DE780E7093F902A0DE7811
|
||||
:4020C000BAF1000F06F0030607DA012E0CBF07260D264E7181F8018006E0012E0CBF052609264E7181F801C00833CBE70135092DC3D1C1680A328B1C0A440C20083393427D
|
||||
:4021000009D013F8081C13F80A5C01F07F0100FB01418D72F2E7FFF767FF114B0121186000230C2000FB0142D3801289013113449BB203F00102134409299BB2F2D1BDE8C9
|
||||
:40214000F84FFFF767BEBDE8F88F00BF1493FF1FFA92FF1F8293FF1F0D93FF1F0B93FF1F1093FF1F114B1B7903F07F035A1E072A19D80F490C2202FB031291781B0141F048
|
||||
:40218000010191700021D170517841F002015170127912F0800F074A1A4414BF8D2389239370FFF715BC0020704700BF006000401493FF1FFC5F004030B4194B1A7902F0D5
|
||||
:4021C0007F02531E072B27D8164B0C2404FB02339978154D01F0FE0199700021D97029461201505D114400F07F0050555A7802F0FD025A701A795B78120605D5012B01D1A6
|
||||
:402200008C7006E00D2303E0012B0CBF082309238B7030BCFFF7DCBB002030BC704700BF006000401493FF1FFC5F004010B50D4B0D4C21791878C9B20138C0B2FFF72EFE7D
|
||||
:4022400043681B798B4201D2012909D8074A0848535CDBB24354A3780120DBB2535410BD002010BD0D93FF1F00600040FA92FF1F8293FF1F38B58A4A8A4C13780021DBB2CB
|
||||
:4022800021801806517840F18D800A2900F20581DFE811F05D00030103010301030103010B0003017E0003018200D3787C49012B09D17D4B1A787D4B03EBC2035B685B68F0
|
||||
:4022C0006360122310E0CB78022B12D18878FFF7E5FD002800F0E180436863606368DA7863689B7843EA02232380BDE83840FFF78FBCCB78032B26D16D4B00228878D5B2CD
|
||||
:40230000854209D3664A91786A4AEE2908BF1346634A917881B106E0187801320028F1D018780344EAE764499278097C914203D16248FFF739FD614B1A78002A00F0AD80F6
|
||||
:402340001A78228018E0BDE8384000F025BF13F0030313D0022B40F0A0802380504B0C211B7903F07F02564B01FB02339A78554BD2B21A7000225A706360B6E702222280C0
|
||||
:40238000514A11784F4AC9B2117053706260ACE7012323804D4BEFE70123238013794C4A1344E9E701390A2977D8DFE801F037764F76067676760A7620009378454ADBB2F2
|
||||
:4023C0005AE0937803F0FF0153B9404B1A7891425FD01970404B01201870FFF715FE58E0481EC0B2FFF75AFD0028EED155E0FFF71DFF002851D02A4A384913791279DBB247
|
||||
:40240000D2B20A70364A3249D25CCB5C9A4240D0314B01221A70FFF753FD3AE003F00303012B2BD009D3022B37D11D4B9B78002B33D1BDE83840FFF7BFBE194B9B78012BCB
|
||||
:402440002BD1214A137803F0FD0315E003F00303012B13D008D3022B1FD1114B9B78E3B9BDE83840FFF77EBE0D4B9B78012B14D1154A137843F0020313700AE0084B1A7937
|
||||
:402480005AB998781B791749DBB2CA5C22EA0002CA54BDE83840FFF79BBA002038BD00BF00600040FC92FF1F0893FF1FD03C0000343D0000BC3C0000A73D0000A093FF1F3B
|
||||
:4024C0001493FF1FB992FF1F0B93FF1F0D93FF1FFA92FF1FF892FF1F0C93FF1F0993FF1F8293FF1F0F93FF1F074B1A78120609D55B78012B06D1054B054A5A6012781A804B
|
||||
:40250000FFF786BB0020704700600040FC92FF1F943C0000014B1870704700BF7F640040014B1878704700BF69640040014B1870704700BF78650040064A0123136002F65F
|
||||
:4025400088321268E0211064034A1170A2F540721360704780E100E000E400E0014B1870704700BF72640040014B1870704700BF7665004073B515461E460B4C052300221F
|
||||
:40258000019200920A4601461846237000F064F932462946207800F01FF90221207800F009F9207802B070BDD080FF1F064A0423136002F688321268E0219064034A11702F
|
||||
:4025C000A2F202321360704780E100E002E400E0014B04221A60704700E100E0014B04221A60704780E100E0014B1870704700BF78640040704738B505460078012428B1CF
|
||||
:4026000000F062FD285D0134E4B2F8E738BD08B50D2000F059FDBDE808400A2000F054BDF7B516461F460B4C00230325019300930A4601462846257000F00EF93A46314621
|
||||
:40264000207800F0C9F80221207800F0B3F8207803B0F0BDE080FF1FF7B516461F460B4C00230225019300930A4601462846257000F0F2F83A463146207800F0ADF8294609
|
||||
:40268000207800F097F8207803B0F0BDE180FF1FF7B516461F460B4C00230125019300930A4601462846257000F0D6F83A463146207800F091F80221207800F07BF8207842
|
||||
:4026C00003B0F0BDE280FF1F73B515461E460B4C0023019300930A4601461846237000F0BBF832462946207800F076F80221207800F060F8207802B070BD00BFE380FF1FB0
|
||||
:40270000024B1878C0F38010704700BF8F450040074A7F23802113705170064A013BDBB202F80839002BF9D1034A1370704700BFE480FF1FF87B00400078004017280FD875
|
||||
:40274000084B0001C25C11B142F0200201E002F0DF02C254C25C42F00102C25400207047012070471070004017280BD8064B0001C25C02F0FE02C254C25C02F0DF02C2548E
|
||||
:4027800000207047012070471070004017280DD8074900010B4603441A7942F004021A71435C43F00103435400207047012070471070004017280BD8064A0001835C4900D0
|
||||
:4027C00003F0F10301F00E011943815400207047012070471070004041F6FF73994208BF4FF400519A4208BF4FF4005217289FBFC00000F1804000F5EC4081809ABFC28070
|
||||
:40280000002001207047000017289FBF034B00011954002088BF0120704700BF1970004017289FBF054B00011A5C01F007019DBF1143195400200120704700BF147000408B
|
||||
:4028400017289FBF034B0001185C00F0070088BFFF20704714700040172810B51AD8C00001F07F0100F1804441EAC21204F5EC44D2B222709DF8082003F00F0343EA021302
|
||||
:40288000DBB263709DF80C30002003F00F03A370E07010BD012010BD10B500F075FC0A4A5378182B0AD91478013B5370E30003F1804303F5F0431B78137000E0FF2400F0E0
|
||||
:4028C00067FC204610BD00BFE480FF1F030610B5044611D400F058FC084AE300117803F1804303F5F04319705378147001335370BDE8104000F04CBC10BD00BFE480FF1F56
|
||||
:4029000030B504060CD411F4704509D1C40004F1804404F5F0442180A270E370284630BD012030BD03065FBFC00000F1804000F5F04081805ABFC28000200120704700000A
|
||||
:4029400038B50446084DB4F5004F05D9286800F013FCA4F50044F6E7034B58686043BDE8384000F009BC00BFEC80FF1F024B1B7A584300F001BC00BFEC80FF1F0E4B00F024
|
||||
:4029800003001A78490102F0FC02104318701A7801F0600142F080021A701A7802F07F021A701A7802F09F020A431A701A7842F010021A70704700BF83430040014B012275
|
||||
:4029C0001A70704784430040044B00F00F021B6853F8220043F82210704700BF08ED00E0054A00F01F00126800F1100352F8230042F82310704700BF08ED00E000F01F0087
|
||||
:402A000000F16040490100F56440C9B2017070470F4B10B50F4900240F205C609C60DC601C615C61FFF7D0FF0B4A136843F0040313600A4B4FF47A72DB68B3FBF2F3084A99
|
||||
:402A40001360084B4FF400421C60C3F8E82010BDBC92FF1FBD2A000010E000E0EC80FF1F14E000E018E000E0024A136843F002031360704710E000E008B5FFF7F5FF034AB9
|
||||
:402A8000136843F00103136008BD00BF10E000E010B5054CA3691BB9FFF7BAFF0123A361BDE81040FFF7E8BFBC92FF1F024B1868C0F30040704700BF10E000E038B5FFF7E9
|
||||
:402AC000F5FF012808D1054D002455F8243003B198470134052CF8D138BD00BFC092FF1F024B03EB8003586859607047BC92FF1F134B144A1B78DBB20360127843EA02236E
|
||||
:402B0000114A0360127843EA0243104A0360127843EA026303600E4B0E4A1B78DBB24360127843EA02230C4A4360127843EA02430A4A4360127843EA02634360704700BF2E
|
||||
:402B40000301004904010049EC460040020100490101004900010049050100490601004910B500F011FB204A044613780A2043F002031370137C43F00203137412F80A3C45
|
||||
:402B800043F0010302F80A3C937943F00103937102F5AB52137843F003031370134B18221A7013F8012C42F0400203F8012C13F8012C02F0FC0203F8012CCE2203F8062CB9
|
||||
:402BC000A3F597530222183B1A70094A137843F008031370FFF7CAFE064B10222046BDE810401A6000F0D4BAAB4300400E5900402F5B004080E200E008B500F0C5FA0F4A79
|
||||
:402C0000137803F0FE031370A2F5AA521D3A137803F0FD031370137C03F0FD03137412F80A3C03F0FE0302F80A3C937903F0FE039371BDE8084000F0ABBA00BF0859004074
|
||||
:402C4000044A137803F03F0343EA8010C0B21070704700BF08590040082804D00A280CBF8223C22300E0422308380E4AC0B20428137098BF0C4B4FF0000298BF33F9101065
|
||||
:402C80000A4B88BF11461A8042F210734B4341F2883103F6C41393FBF1F305490B60054B1A8070470A590040803C00008A93FF1F8C93FF1F9093FF1F08B5102000F0A6F926
|
||||
:402CC00007210420FFF79AFE07490420FFF788FE064A0C20137843F006031370FFF7BCFF034B00221A8008BDB12D0000095900408893FF1F10B5054C23781BB9FFF7DCFFB5
|
||||
:402D000001232370BDE81040FFF72ABFD892FF1F044B1A7802F0FB021A701A7842F001021A7070470859004010B5084B1C7814F0010403D10028F9D0002404E02046FFF79F
|
||||
:402D400015FE024B1B78204610BD00BF09590040034A044B1B881088181A00B2704700BF9093FF1FA25B00400E4A13881BB223B111880A2309B2594301E00B4B19680B4B5E
|
||||
:402D80001B88C01A42F2107300B203FB00F2022391FBF3F30028D8BF5B42134493FBF1F000B270478A93FF1F8C93FF1F8893FF1F7047000010B500F0E7F9214A04461378DE
|
||||
:402DC0000A2043F001031370137C43F00103137412F80A3C43F0020302F80A3C937943F00203937102F5AA521832137843F003031370144B18221A7013F8012C42F040023F
|
||||
:402E000003F8012C13F8012C02F0FC0203F8012CCE2203F8062CA3F597530222123B1A70094A137843F008031370FFF79FFD074B08222046BDE810401A6000F0A9B900BFED
|
||||
:402E4000AB43004006590040275B004080E200E008B500F099F90F4A137803F0FE031370A2F5AA52153A137803F0FE031370137C03F0FE03137412F80A3C03F0FD0302F8BC
|
||||
:402E80000A3C937903F0FD039371BDE8084000F07FB900BF00590040044A137803F03F0343EA8010C0B21070704700BF00590040082804D00A280CBF8223C22300E04223C0
|
||||
:402EC00008380E4AC0B20428137098BF0C4B4FF0000298BF33F910100A4B88BF11461A8042F210734B4341F2883103F6C41393FBF1F305490B60054B1A8070470259004092
|
||||
:402F00008A3C00009693FF1F9C93FF1F9493FF1F08B5102000F084F807210320FFF76EFD07490320FFF75CFD064A0C20137843F006031370FFF7BCFF034B00221A8008BDE5
|
||||
:402F400009300000015900409893FF1F10B5054C23781BB9FFF7DCFF01232370BDE81040FFF728BFD992FF1F044B1A7802F0FB021A701A7842F001021A70704700590040D2
|
||||
:402F800010B5084B1C7814F0010403D10028F9D0002404E02046FFF7E9FC024B1B78204610BD00BF01590040034A044B1B881088181A00B2704700BF9493FF1FA05B004031
|
||||
:402FC0000E4A13881BB223B111880A2309B2594301E00B4B19680B4B1B88C01A42F2107300B203FB00F2022391FBF3F30028D8BF5B42134493FBF1F000B270479693FF1FD3
|
||||
:403000009C93FF1F9893FF1F70470000034A00F0F800137803431370704700BF02410040034A00F0F800137803431370704700BF06410040014B1870704700BF76640040D7
|
||||
:40304000014B1870704700BF7C64004073B515461E460B4C04230022019200920A46014618462370FFF7F8FB324629462078FFF7B3FB02212078FFF79DFB207802B070BDE6
|
||||
:40308000FC80FF1F074A0223136002F688321268E0215064044A11706FF440710A441360704700BF80E100E001E400E0014B1870704700BF74650040014B1870704700BFDF
|
||||
:4030C0007764004000000000FEB5494652465B460EB40746244909688A46244A12682448022100F071F8030020480068C018204900F06AF8143883460121C9430C4601258C
|
||||
:40310000002600F041F8814651460B7823400B705846013000F030F83800F04028400B78234003430B70584600F026F80136072EF2D9002001300138013001200B7823407E
|
||||
:4031400003430B705846043000F016F8484600F01FF800BF00BF00BF0EBC894692469B46FEBD00BFAFF30080D480FF1FF880FF1F00C20100000000000230800803D000BFE7
|
||||
:4031800001380046FCD17047EFF3108072B6704780F31088704700BF094A137803F00303012B0AD0022B09D113790C2103F07F02044B01FB02339B7A00E013790020704751
|
||||
:4031C000006000401493FF1F002902D0B0FBF1F0704708B14FF0FF3000F008B80029F8D00246B0FBF1F000FB11217047704700BF014B1868704700BF6081FF1F0E4B70B577
|
||||
:403200001E460E4C0025E41AA410A54204D056F8253098470135F8E700F0E2FD084B094C1E46E41AA4100025A54204D056F8253098470135F8E770BDEC3D0000EC3D000024
|
||||
:40324000EC3D0000F43D000003460244934202D003F8011BFAE7704730B5141E05469BB0184604DA8B232B604FF0FF301DE04FF40273ADF80C300CBF234604F1FF330293F9
|
||||
:4032800005934FF6FF7300910491ADF80E3002461E9B6946284600F073F8431CBCBF8B232B6014B1009B00221A701BB030BD000007B5009313460A46014603480068FFF77E
|
||||
:4032C000CBFF03B05DF804FB6081FF1F2DE9F0478E6882469E420C46914698463ED88A8912F4906F3AD02568096902236F1A656905EB450595FBF3F57B1C43449D4238BFB3
|
||||
:403300001D4653050FD5294600F04AFB064698B13A46216900F0D2FAA38923F4906343F08003A38113E02A4600F098FB064670B92169504600F0E8FA0C23CAF80030A38945
|
||||
:403340004FF0FF3043F04003A381BDE8F08726613E44266046466561ED1BA560464528BF464649463246206800F0B3FAA36800209B1BA36023681E442660BDE8F08700009E
|
||||
:403380002DE9F04F9DB003938B8980461C060D4616460DD50B695BB9402100F001FB2860286118B90C23C8F80030CDE040236B610023099320238DF82930DFF89CB130233F
|
||||
:4033C0008DF82A3037463C4614F8013B1BB9B7EB060910D003E0252BF9D02746F3E74B46324629464046FFF771FF013000F0A780099B4B4409933B78002B00F0A080002373
|
||||
:403400004FF0FF3204930793059206938DF853301A930126052221784E4800F041FA671C049B38B14B4A3C46801A06FA00F018430490EFE7D90644BF20228DF853201A07B0
|
||||
:4034400044BF2B228DF8532022782A2A03D0079A00210A200BE0039A111D12680391002A10DA524243F00200079204900BE027463B780134303B092B03D800FB023201217E
|
||||
:40348000F5E701B107923B782E2B1ED17B782A2B0AD1039B02371A1D1B680392002BB8BF4FF0FF33059310E0002319460593781C0A2407463A780130303A092A03D804FB83
|
||||
:4034C00001210123F5E703B1059103223978224800F0E6F940B14023CBEB000003FA00F0049B013718430490397806221B487E1C8DF8281000F0D4F988B1194B33B9039B1D
|
||||
:40350000073323F007030833039314E003AB00932A46144B04A94046AFF3008007E003AB00932A460F4B04A9404600F093F8B0F1FF3F824603D0099B5344099342E7AB89BC
|
||||
:403540005B0601D4099801E04FF0FF301DB0BDE8F08F00BFBB3D0000C13D0000C53D000000000000CD3200002DE9F04791461F460A698B6806469342B8BF1346C9F80030AD
|
||||
:4035800091F843200C46DDF8208012B10133C9F800302368990642BFD9F800300233C9F80030256815F0060510D104F1190A07E00123524639463046C04701301AD0013598
|
||||
:4035C000E368D9F800209B1A9D42F1DB94F843302268003318BF012392060FD5E118302081F843005A1C94F845102244023382F8431003E04FF0FF30BDE8F08704F1430291
|
||||
:4036000039463046C0470130F4D02268D9F80050E36802F00602042A08BF5D1B2269A3680CBF25EAE57500259342C4BF9B1AED184FF000091A344D4509D00123224639462F
|
||||
:403640003046C0470130D5D009F10109F3E70020BDE8F0872DE9F04317460A7E85B06E2A984606460C460C9B01F1430E00F0AE8011D8632A22D009D8002A00F0BB80582A3E
|
||||
:4036800040F0CA8081F84520834955E0642A1ED0692A1CD0C0E0732A00F0B08009D86F2A2ED0702A40F0B8800A6842F020020A603EE0752A24D0782A3AD0ADE01A6801F151
|
||||
:4036C0004205111D1960136884F84230A8E021681A6811F0800F02D0111D196008E011F0400F02F10401196002D0B2F9003000E01368002B3CDA2D225B4284F8432037E003
|
||||
:4037000021681A6811F0800F02D0111D196007E011F0400F02F10401196001D0138800E01368227E5C496F2A14BF0A2208221BE078225A4984F845202268186812F0800F4B
|
||||
:4037400000F104051D6003D1550601D5038800E00368D00744BF42F0200222601BB9226822F0200222601022002084F8430001E049490A226568002DA56008DB206820F009
|
||||
:40378000040020602BB9002D7DD175460CE0002B79D07546B3FBF2F002FB1033CB5C05F8013D03460028F5D1082A0BD12368DA0708D5236962689A42DEBF302305F8013C34
|
||||
:4037C00005F1FF35C5EB0E0323612EE008681A6810F0800F496903D0101D1860136808E010F0400F02F104001860136801D0198000E0196000232361754616E01A68111D3A
|
||||
:403800001960156800216268284600F049F808B1401B6060636804E004F1420584F8422001232361002384F84330CDF800803B4603AA21463046FFF797FE013002D14FF093
|
||||
:40384000FF3026E023692A4639463046C0470130F5D023689B0710D5002504F1190907E001234A4639463046C0470130E7D00135E368039A9B1A9D42F2DBE068039B984219
|
||||
:40388000B8BF184605E00B7804F1420584F842308AE705B0BDE8F0836F3C0000CC3D000010B5C9B202449042034605D01C7801308C42F8D1184610BD002010BD10B5431E9F
|
||||
:4038C0000A44914204D011F8014B03F8014FF8E710BD884210B501EB020301D8421E0BE09842FBD28118D21AD34204D013F8014D01F8014DF8E710BD994204D011F8014B7E
|
||||
:4039000002F8014FF8E710BD38B50546002944D051F8043C0C1F002BB8BFE41800F0D4F81E4A1368114613B96360146030E0A3420DD92268A018834201BF18685B681218C2
|
||||
:40394000226063600C6023E0A24203D813465A68002AF9D118681918A1420BD12168014458188242196013D110685268014419605A600DE002D90C232B6009E021686018E0
|
||||
:40398000824201BF106852680918216062605C602846BDE8384000F098B838BDE092FF1F70B5CD1C25F0030508350C2D38BF0C25002D064601DBA94202D90C23336046E015
|
||||
:4039C00000F082F8234B1C681A462146A1B10B685B1B0ED40B2B03D90B60CC18CD501EE08C420BBF63684B681360636018BF0C4615E00C464968E9E7174C23681BB9304696
|
||||
:403A000000F052F820602946304600F04DF8431C18D0C41C24F00304A0420DD12560304600F053F804F10B00231D20F00700C31A0ED05A42E25070BD211A304600F034F8A0
|
||||
:403A40000130EBD10C233360304600F03EF8002070BD00BFE092FF1FDC92FF1FF8B5074615460E4621B91146BDE8F840FFF798BF1AB9FFF749FF2846F8BD00F027F88542C5
|
||||
:403A80000ED929463846FFF78BFF044650B131462A46FFF713FF31463846FFF735FF01E03046F8BD2046F8BD38B5064C0023054608462360FDF7DCFB431C02D1236803B178
|
||||
:403AC0002B6038BDC493FF1F7047704751F8040C0028BEBF091851F8043CC0180438704700000000050209020B020D020F021102130215027265706C79203078253032787F
|
||||
:403B000000686F6D696E6700626567696E6E696E67207365656B2066726F6D20256420746F2025640066696E6973686564207365656B00796573006E6F00647269766520E7
|
||||
:403B4000303A20257320647269766520313A2025730057616974696E6720666F72205553422E2E2E0055534220726561647900636F6D6D616E64203078253032780066614C
|
||||
:403B8000696C2025642B25642B2564203D3D2025642C206E6F74202564007061737365643D256400756E64657272756E206166746572202564207061636B65747300636F25
|
||||
:403BC000756E743D256420693D256420643D256400636D645F777269746500646F6E6520256420256400703D25642063723D25642063773D256420663D256420773D2564FF
|
||||
:403C000020696E6465783D256420756E64657272756E3D25640077726974652066696E69736865640073746172742065726173696E670073746F702065726173696E670092
|
||||
:403C400069646C650000510040100040510040300000000140001000140140000800400140000A004C014000020050014020003031323334353637383941424344454600E9
|
||||
:403C8000000100000004000000100001000000040000001028000000000104000100000000000000000157494E5553420000303030303100000000000000000012034D0080
|
||||
:403CC0005300460054003100300030000100000001000000D83C000001000000A73D0000000000000000000001000000F03C000001000000793D000004000000123D000014
|
||||
:403D0000000000000000000000000000103D0000FF00000001024000FF00000082024000FF00000003034000FF00000084034000FF00020304030904160346006C007500CE
|
||||
:403D4000780045006E00670069006E0065002A0343006F0077006C00610072006B00200054006500630068006E006F006C006F0067006900650073000009022E0001010036
|
||||
:403D800080320904000004FF00000107050102400000070582024000000705030340000A0705840340000A12010002FF0001080912006E0100020180014300232D302B20AF
|
||||
:403DC00000686C4C00656667454647003031323334353637383961626364656600000000F8B500BFF8BC08BC9E46704759000000ED120000F8B500BFF8BC08BC9E467047E7
|
||||
:403E000035000000183E0000C880FF1FA0000000601200000000000000000000C893FF1FFF000000675000400C00000007000000FFFFFFFF7F8000003F0000000000007D46
|
||||
:403E400000FA0000400000000090D003FF0000000000000000000000000000000000000000000000000000000000000000000000B93D0000000000000000000000000000B0
|
||||
:403E80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000081FF1F00000000000000000000000063
|
||||
:403EC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C2
|
||||
:403F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000081
|
||||
:403F40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041
|
||||
@@ -4098,68 +4098,68 @@
|
||||
:40FF80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041
|
||||
:40FFC0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
|
||||
:0200000480007A
|
||||
:40000000014500400752004005640040010101400303014001050140010701400D090140100A0140460B01405C0C0140490D0140590E0140360F014001150140031701407A
|
||||
:400040002418014035190140061B01400C4001400D4101400742014005430140054401401445014008460140094701400948014008490140174C0140044D014005500140AF
|
||||
:40008000035101407E020803094610831196601561047C402B802D0A3B7E3E807E01E208E224E602EE02E020EA0188849140980199809C809D209E409F20A140A280A4408A
|
||||
:4000C000AF10EA09050408030E01110120022D0231043302360337013F45580B59045B045C095F0100800120058507040E601240171819801C201D2D1F0A21052301251099
|
||||
:40010000260C27182A402F2A3002361838083D223E403F04452A4E88560858805F506409668068026C046D40780179407B01830185058B408C489240930494409B049C01D3
|
||||
:400140009D859E889F28A143A210A320A410A604A701AD80C0F3C230C468CA78CC61CEF2D0E0D220D638D830DE01E029E402E808001002400403060C080209010B021201CF
|
||||
:4001800014031674170118191A621B061E80228024102628281029012B042F01307F327F34803507382A3E10580459045B045C995F018018820184078502863889488A047E
|
||||
:4001C0008B908D088F349028945095FD97029B029C209D02A006A102A3FDA402A503A7F8A838AA07AC80ADA0AF48B040B23FB307B401B5C0B680B738BBA0BE51C021C720DA
|
||||
:40020000C820C9FFCAFFCBFFCD20CEF0D110D804D904DA04DB04DC99DD09DF01E108E240E340E480E640E740010A02040515080809800A800E680F0210A212081608170980
|
||||
:40024000180519081B0A1D021E201F1421D0220826202704290A2A802D802F0430A03208362439A03A043C20400550025C405F2068016D806F018302870288018B108C0233
|
||||
:4002800092C09304980899129A049C019D0C9E80A0A0A101A320A410A580A61CA708AC02B0A0B310C07EC2FDC47FCA3BCC6ECE2ED00CD630E008E220E6020447050A063891
|
||||
:4002C00008040C310E4A0F0510081201150D162019011C082004240428492A16303F33033440350C3A033E10406441034302452446E04705481B49FF4AFF4BFF4D204EF0B5
|
||||
:40030000511056085804590B5A045B045C995D995F0161086280630C64406540664067A8684069A86B086D088001820A8306840F86108701880289018A058B02900292340E
|
||||
:40034000940F9620970199019A0F9B049E40A480A840B038B107B407B6C0BA20D201D610D804D904DB04DC99DD90DF0100400108020405140680080809800A800D020E2AAA
|
||||
:4003800010A0120816101720184019021A041D121E021F602128232425013128361438043B803C203D023F0440404204430848A04A085204531058A0600E62106A806E4015
|
||||
:4003C0007801C077C2FDC46ECC66CEEAD007D204D60CD80CDE01E208EA01E201E680EA0205010F022D023301350239203F14560859045B045D905F01800288018C018F0427
|
||||
:400400009D01A502A804A904AD08AE01B004B10CB301B403B502BE01BF14D608D80BD904DB04DC99DD90DF0101A00240100812021880192020C821082202272429202A4043
|
||||
:400440002B102D4032403680378038403D803F0859145A405F806240632867016A806C086F02780183018B028D108E409140980199809D209E409F20A140A280A444C00BA7
|
||||
:40048000C403CA1ECC08CE58D61ED81EDE01E680EA02A904AB04AD08B440E802EE01170433043402371039043A203E808620C420CCE0CE70E21030203720831084028A08BE
|
||||
:4004C0009C029E809F10AD04CC30E220E640EE40560889809A089E809F20A420D4409E809F20A580A820EA8014407E018710C404DE045104564058405D8062086740858012
|
||||
:40050000871088408A018E4096029710B040D407D604D803E005E402EA01820286088740924095089770A608AE400B210F149240950897B1A202AB01AF40C20F25808280E6
|
||||
:400540008B029E80A580AF20C820E280EA4073807F029B80A302AB80DC80DE20EA8005200B800C020D040F08520254205E4061028C028F04924095089780A202AF04C001D7
|
||||
:40058000C20DD403D604D802E202E602A920AD02B420EC0801010D010F0111011D0100BD012A10050820324039804620082010C42000080280000000FE1001ED00E3001C2E
|
||||
:4005C00000000000000000000000040182EF3D10000000083800C11F07E0000000080220000010004603020000E0000412FFFFFF0020F00120100000000008000404040460
|
||||
:4006000099990001000800004020800840200008000040A8000000000000000000000000000000003F0000201F001F0000000000000000001000000040000000000000005A
|
||||
:40064000C0000000FF0000B84700470000010000A000003FBF009F000000000000010000000000000000000000000000000000000000000000000000000000000000000036
|
||||
:40068000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003A
|
||||
:4006C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FA
|
||||
:4007000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B9
|
||||
:400740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000079
|
||||
:400780000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000039
|
||||
:4007C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F9
|
||||
:4008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B8
|
||||
:400840000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000078
|
||||
:400880000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038
|
||||
:4008C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F8
|
||||
:4009000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B7
|
||||
:400940000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000077
|
||||
:400980000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000037
|
||||
:4009C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F7
|
||||
:400A000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B6
|
||||
:400A40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000076
|
||||
:400A80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000036
|
||||
:400AC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F6
|
||||
:400B000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B5
|
||||
:400B40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000075
|
||||
:400B80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035
|
||||
:400BC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F5
|
||||
:400C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B4
|
||||
:400C40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000074
|
||||
:400C80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034
|
||||
:400CC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F4
|
||||
:400D000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B3
|
||||
:400D40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000073
|
||||
:400D80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000033
|
||||
:400DC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F3
|
||||
:400E000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B2
|
||||
:400E40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000072
|
||||
:400E80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000032
|
||||
:400EC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F2
|
||||
:400F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B1
|
||||
:400F40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000071
|
||||
:400000000145004008520040015B004001650040010101404D0201403D0301404C0401404D0501404D060140500701404B0801404B0901404B0A0140500B0140470C0140CB
|
||||
:40004000500D0140520E0140350F014046140140541501404B160140561701404718014044190140591A0140571B01400A400140104101400E4201400943014004440140BE
|
||||
:400080000D4501400A4601400F470140094801400F4901401B4C0140084D014008500140045101407E0208440905108011821801600C610A7C4027212A0A8C8000010109B1
|
||||
:4000C0000202040805090808090F0B100C080D010F02100F1120140416011709180819101B0E1D011E01210422082301240829092A0E2C0D320F331F35203B083E043F1020
|
||||
:400100005608580459045B045C905D905F01850287018C01900F9401960898249A089E07A008A101A222A302AA08AE10B01FB101B302B420B90ABE10BF05C202C70EC810AC
|
||||
:40014000C9FFCAFFCBFFCF83D804D904DA04DB04DC09DD09DF01030204A10620074008010A060B200C800D100E400F2010421110150416821720180419011E10202021010F
|
||||
:40018000262027202A012C042E023508376138083E583F0240045208588859215A025D4060026108621265806F0180068140874088408A088E209880C0F1C2FFC4FBCAA1EC
|
||||
:4001C000CCF0CEF2D004D61FD81FE20CE6C5EE82010D04020601070109080C010D080E0E100F130E150F161019081C201D082101220F2302240125042604270128012908CA
|
||||
:400200002A082C012F08301F3220330F3E043F045608580459045B045C095D905F01810182088302840885028A108B018C088D038F049102920194049701982099029A1FB5
|
||||
:400240009C089D02A202A302A408A501A704A808A902AC1FAD03AE20B107B43FBF01D804D904DB04DC09DF0100400108048006A0070809880A400C810E080F20100511082C
|
||||
:40028000130115251740185019011B011E081F20210827402AA02B902C052D022F20308031213208350136803728388039243B013D083E4A3F2158405C105D806180851076
|
||||
:4002C00087029102938094A195349644972099809B209C0C9D089EBAA480A602A713A908AC03B010B520B601C0F5C2FDC4FFCAFFCCFFCEFFD638D808E20AE648E880EA03A0
|
||||
:40030000EE820003010D050506010801090C0B020C010D0D1001111012021602170D1801190D1C011D0D2201230D2401250D280129092C012D012E022F02310C3510360355
|
||||
:4003400037033E403F51580459045B045F0180208102820F8404860A882F89028D028EA09204948095039640970C98049A099E10A020A102A20FA480A802AC01AD0AAF0550
|
||||
:40038000B060B108B21FB306B480B501B61FBE10BF01D804D904DB04DC99DF01000902080302048A0708082209880C800D100F9011501305158016A01710180919041A08AD
|
||||
:4003C0001BD21D80210923042440254026102B422C042D012E402F20310836843721380239803A103D203E083F825D015F0169506AA06F0178017B807D027F8080048604BE
|
||||
:4004000089108A028F01938094A19525964497219B209C0D9D0A9EA89F08A321A480A520A68AA790AD01B040B210C0FFC2FFC4FFCAF9CCF2CEFDE242E401EA01000103027E
|
||||
:4004400004E0050108010A080B020CE00F02100F1280130814481602170218201B021E071F02200422482302261027022A082B042F10311F34E0361F382039023F015804DF
|
||||
:4004800059045B045C095F0180038109840387318A018B098C038F06900391129309940395099712980399409E02A003A309A603A709A803A909AC03AD49AF24B338B40349
|
||||
:4004C000B540B707BB88BE10D804D904DB04DC90DF010080012002800320048A052008180A010B400C020D080E0610021325172918081E061F802002215423252480284155
|
||||
:4005000029202B202C872D202F203108321233013448350137A0380239883B103C803E043F115A806E408340860287048A0690029289935094019704981A99019B889C84CD
|
||||
:400540009D209F20A0C2A108A280A328A401AB10B204C0FFC2FFC47FCAFFCCF7CEFFD608E080E620EA85EE2002800404050D064808200A400C0111011210144816021A07E2
|
||||
:400580001B051C401E202608280129102A082C0F2D0A3020310C32C03303341F362037103A083E413F4056085804590B5B045C995D905F01822083018607870F88218A0825
|
||||
:4005C0008B018C218F019210930E9428964297059AC89B039F01A02FA280A301A444A628A709A90FAA20AD0FB105B21FB4E0B503B709BA20BF51D804D904DC09DF010001EA
|
||||
:400600000184030805A4078009090A060D080E881006121015141701180219811A051B481D041E081F20210422412501264027082B052C822F2432113408350137A03908B7
|
||||
:400640003C823D043F144410450858805B10630A64086610780284018601911092289358950896019704980A9B819D249F20A0C2A108A280A401A761A840AF11B040B504F1
|
||||
:40068000B702C0FFC27FC477CAFCCCF5CEF2D60CD80CDE01E202E640E880EA10EE4002080349077F08010A280B090C2F0F091001117F1408160217091A071B091E401F2962
|
||||
:4006C000221023722709280429782A282B042F19310732603348341F352837183F55580459045B045C095F01802081048440850186A088418A088C4F8E808F04920794041B
|
||||
:40070000966898689A029B019C41A208A610AA40AD02B01FB304B503B6E0BA80BF04D608D804D904DB04DC99DD90DF010128024003010521070109040A810B080D080E0633
|
||||
:400740000F80128013181608170218821A801D081E041F14221423102601271A2B012D042E012F253210341036843721380239083A403C023D1A3E0A3F54584060026240FE
|
||||
:4007800068026B016F0A831886408B048C018D089342951496019714980899019B809C109D209E0A9F21A0C0A284A402A509A74AB308B504C0DFC2FFC45ECAF8CCF4CEFBE6
|
||||
:4007C000D608D808E010E280E644EE820002012F020103800402060107070A060B200C020E010FC81002120114071528174218021A011B101C021E012121220523082544DD
|
||||
:400800002607272829212A012C0731E03207331F3B023E04580459045C905F0182698502861988198E198F119019924493049419962298229A199B089C19A20EA306A61923
|
||||
:40084000A702A910AA19AB01AD01AE19AF10B070B208B301B407B510B607B70EB928BAA2BB80BE04BF14D804D904DB04DC99DF010082012402400521060207200810094941
|
||||
:400880000B200C020D090E010F04104213141514164017801A201C821D011E281F012010210423C025442680270829202A082B402C802F1A30803108329034483614378162
|
||||
:4008C000390A3B503D403F046D408C10C0FFC2FFC4FFCAF7CCA6CE5FE210010E04080508060409080C0D0E020F08110812091504180819081A021D081E04200423012702A7
|
||||
:4009000029082D08300C320C330F34033A0A3F045608580459045B045C095D905F01801382048402871088028B1F8C088E018F1F901991019202951F96099A089B049C0273
|
||||
:400940009D1FA001A20CA308A602A720A802AB02AC1BAD1FB210B40FB73FBB80BE14D804D904DC90DF010108021104020540060807200A040B810D110F2211021405161004
|
||||
:400980001702190A1A041E201F20210425402680270229442A212C802E202F2130803120320433113545371039163A803B033D843F2058806002680D6A508101821084A1C0
|
||||
:4009C000880289028B048E5090029134922893859508980599459AA99B219C229D0AA080A121A311A40CA690AA88AD80AF10B111B504B648C0F5C2FBC4F8CAFFCCFFCE7FAE
|
||||
:400A0000D608D808E248E401E602E809EE030001062008010A7E0D010E08107F167F1A041E1020022101247E26012A402C7F3501367F3B303E40580459045B045C905F0179
|
||||
:400A4000804484118708881189078C078E088F109211941195A5974298119B429C119F21A011A307A433A5C6A644A721A878AA02AC20AD84AE02B3E0B51FB67FB71FB9A0BC
|
||||
:400A8000BE40C004C5E0C6C0C80AC9FFCAFFCBFFD004D601D804D904DA04DB04DC90DD09DF01E2C001160201030204020540071409A80B400C810D200F2010041141130440
|
||||
:400AC00015A016A019801F80214023152510270428222B402F8030083250384039083B103D8041014B025210688069756B116C016E406F02705071E972A07348810A8204C4
|
||||
:400B00008404850487048A108C509040910292A8938094A295A496409733980199049B209C269D0A9EB89F18A141A351A484A530A68CA808B210B540C0FFC2FFC4FFCA8B79
|
||||
:400B4000CC0ECE1ED001E003E208E402EA40EE060601083109100D0C0E080F021040130116021702180319011A101E0420382304240325082608290A2B042C022E2130400E
|
||||
:400B8000310F3207351036383A803E013F10580459045B045C995F018001830C8401870188018A028B078C018F019001930194019701980199079E019F01A001A108A302BA
|
||||
:400BC000A601A701A801AB01AC01AE02AF01B507B603B708BE40BF50D804D904DF0100820201032A05480608081909800B400D080E461002128013241501174818011D4E2B
|
||||
:400C00001E01218022102408260228082BA22C082E022F103011328436063710380239A83D103F806D5080048280850186058C208D01900291A89248934494019620981A26
|
||||
:400C40009A029B609C809D20A043A284A328AB80B604C0EFC2FFC4BFCAEFCCEFCE3FE080E451E8C0EE02000801010201050108040B010C010D010E081101130217011901F5
|
||||
:400C80001A011D01210123022401250129012A022D01300332043303340836083A023E543F0440434502480149FF4AFF4BFF4D204EF05110580459045A045C095D095F017F
|
||||
:400CC0006108624063406480664067408004840885CC86018722881F8C048D01900493119401961E9722980499F19C019E10A004A344A588A604A824A9AAAA19AB44AC0134
|
||||
:400D0000AE22B020B30FB50EB61FB7F0BE41BF10D804D90BDC90DF01002001020301058907080B040C200D090E011010120816801764181019221A0A1B801D021E0222083E
|
||||
:400D400025602711280929022B202C082E022F10301232843606371039A83A013D884010410248107C0283408520881089088B308C088D448F4091EA920193049602972033
|
||||
:400D8000981B99819A839B0C9D209F10A022A108A286A320A408A601A7C0A904AB04AD01AE01B080B18AB608B708C0FBC2F2C4F6CAEFCCEFCE5FD003DE80E0A0E240E47094
|
||||
:400DC000E602E890ECC01B011F0231203302368037083B40C630CCF0CE103088364037043A023C2088108F0893809F08A520AE80AF41B340CCF0CE60EE4053405640840897
|
||||
:400E00008C8093809A409E029F04A488A520A6C0B2C0D460E2408E0292029E02A520A6C0AB04AE01EA80EE4015027B02C404DC015940670882108E4191029720AF10B7020E
|
||||
:400E4000D401D801E008E602EC021A4085408D049102966097289D40A201C608E60209440F4191029420962097299C409D40A201A544A810AB01B040C20FEA0126809202EF
|
||||
:400E8000A320A520A680AE40B720C820EE405280572079407E01828085208D409202A320A520D460DC80DE20E210E62004200A200C400F401F1050805B405E025F8083408D
|
||||
:400EC000894091029420962097209C409D40A201AF40B304C001C20DC601D405D605E001E801850188809102A480B3C0E401EA04EC04010109010B010D010F0111011B01BF
|
||||
:400F00001D0100FF01AB020211050000BF0000A09F001F000000000000000000100000004000000000000000C0000000FF0000B847004700000100008000000282008200D5
|
||||
:400F400000000000000303000300000027001801270018010004000000050000000000000000000000000000000000000000000000000000000000000000000000000000DF
|
||||
:400F80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000031
|
||||
:400FC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F1
|
||||
:4010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B0
|
||||
@@ -4615,12 +4615,12 @@
|
||||
:0200000490105A
|
||||
:04000000BC90ACAF55
|
||||
:0200000490303A
|
||||
:020000004B149F
|
||||
:0200000005AB4E
|
||||
:0200000490402A
|
||||
:4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C0
|
||||
:400040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080
|
||||
:400080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040
|
||||
:4000C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
:0200000490501A
|
||||
:0C00000000012E16106900002E2A5B7D06
|
||||
:0C00000000012E16106900002E321614AC
|
||||
:00000001FF
|
||||
27
FluxEngine.cydsn/FIFOin/API/c.c
Normal file
27
FluxEngine.cydsn/FIFOin/API/c.c
Normal file
@@ -0,0 +1,27 @@
|
||||
#include "cyfitter_cfg.h"
|
||||
#include "cydevice_trm.h"
|
||||
#include "cyfitter.h"
|
||||
#include "`$INSTANCE_NAME`_h.h"
|
||||
|
||||
void `$INSTANCE_NAME`_Start()
|
||||
{
|
||||
`$INSTANCE_NAME`_Init();
|
||||
}
|
||||
|
||||
void `$INSTANCE_NAME`_Stop()
|
||||
{
|
||||
`$INSTANCE_NAME`_Disable();
|
||||
}
|
||||
|
||||
void `$INSTANCE_NAME`_Init()
|
||||
{
|
||||
`$INSTANCE_NAME`_Enable();
|
||||
|
||||
}
|
||||
void `$INSTANCE_NAME`_Enable()
|
||||
{
|
||||
}
|
||||
|
||||
void `$INSTANCE_NAME`_Disable()
|
||||
{
|
||||
}
|
||||
50
FluxEngine.cydsn/FIFOin/API/h.h
Normal file
50
FluxEngine.cydsn/FIFOin/API/h.h
Normal file
@@ -0,0 +1,50 @@
|
||||
#if !defined(`$INSTANCE_NAME`_H)
|
||||
#define `$INSTANCE_NAME`_H
|
||||
|
||||
#include "cytypes.h"
|
||||
#include "cyfitter.h"
|
||||
#include "CyLib.h"
|
||||
|
||||
#define `$INSTANCE_NAME`_FIFO_PTR ((reg8 *) `$INSTANCE_NAME`_dp__F0_REG)
|
||||
|
||||
/* Macros to clear DP FIFOs.*/
|
||||
#define `$INSTANCE_NAME`_CLEAR do { \
|
||||
CY_SET_XTND_REG8(\
|
||||
((reg8 *) `$INSTANCE_NAME`_dp__DP_AUX_CTL_REG), 0x01u | \
|
||||
CY_GET_XTND_REG8(((reg8 *) `$INSTANCE_NAME`_dp__DP_AUX_CTL_REG)));\
|
||||
CY_SET_XTND_REG8(\
|
||||
((reg8 *) `$INSTANCE_NAME`_dp__DP_AUX_CTL_REG), 0xfeu & \
|
||||
CY_GET_XTND_REG8(((reg8 *) `$INSTANCE_NAME`_dp__DP_AUX_CTL_REG)));\
|
||||
} while(0)
|
||||
|
||||
/* Macros to set FIFO level mode. See the TRM for details */
|
||||
#define `$INSTANCE_NAME`_SET_LEVEL_NORMAL \
|
||||
CY_SET_XTND_REG8(\
|
||||
((reg8 *) `$INSTANCE_NAME`_dp__DP_AUX_CTL_REG), 0xfbu & \
|
||||
CY_GET_XTND_REG8(((reg8 *) `$INSTANCE_NAME`_dp__DP_AUX_CTL_REG)))
|
||||
#define `$INSTANCE_NAME`_SET_LEVEL_MID \
|
||||
CY_SET_XTND_REG8(\
|
||||
((reg8 *) `$INSTANCE_NAME`_dp__DP_AUX_CTL_REG), 0x04u | \
|
||||
CY_GET_XTND_REG8(((reg8 *) `$INSTANCE_NAME`_dp__DP_AUX_CTL_REG)))
|
||||
|
||||
/* Macros to set FIFO to single-buffer mode. */
|
||||
#define `$INSTANCE_NAME`_SINGLE_BUFFER_SET \
|
||||
CY_SET_XTND_REG8(\
|
||||
((reg8 *) `$INSTANCE_NAME`_dp__DP_AUX_CTL_REG), 0x01u | \
|
||||
CY_GET_XTND_REG8(((reg8 *) `$INSTANCE_NAME`_dp__DP_AUX_CTL_REG)))
|
||||
|
||||
/* Macros to return the FIFO to normal mode. */
|
||||
#define `$INSTANCE_NAME`_SINGLE_BUFFER_UNSET \
|
||||
CY_SET_XTND_REG8(\
|
||||
((reg8 *) `$INSTANCE_NAME`_dp__DP_AUX_CTL_REG), 0xfeu & \
|
||||
CY_GET_XTND_REG8(((reg8 *) `$INSTANCE_NAME`_dp__DP_AUX_CTL_REG)))
|
||||
|
||||
void `$INSTANCE_NAME`_Enable();
|
||||
void `$INSTANCE_NAME`_Disable();
|
||||
void `$INSTANCE_NAME`_Start();
|
||||
void `$INSTANCE_NAME`_Stop();
|
||||
void `$INSTANCE_NAME`_Init();
|
||||
|
||||
#endif
|
||||
|
||||
/* [] END OF FILE */
|
||||
BIN
FluxEngine.cydsn/FIFOin/FIFOin.cysym
Normal file
BIN
FluxEngine.cydsn/FIFOin/FIFOin.cysym
Normal file
Binary file not shown.
128
FluxEngine.cydsn/FIFOin/FIFOin.v
Normal file
128
FluxEngine.cydsn/FIFOin/FIFOin.v
Normal file
@@ -0,0 +1,128 @@
|
||||
|
||||
//`#start header` -- edit after this line, do not edit this line
|
||||
`include "cypress.v"
|
||||
//`#end` -- edit above this line, do not edit this line
|
||||
|
||||
/* Ultra-simple FIFO in component: a byte is shifted in every clock when req
|
||||
* is high. */
|
||||
|
||||
module FIFOin (drq, clk, d, req);
|
||||
output drq;
|
||||
input clk;
|
||||
input [7:0] d;
|
||||
input req;
|
||||
|
||||
//`#start body` -- edit after this line, do not edit this line
|
||||
|
||||
wire [7:0] pi;
|
||||
assign pi = d;
|
||||
|
||||
wire load;
|
||||
assign load = req;
|
||||
|
||||
cy_psoc3_dp #(.cy_dpconfig(
|
||||
{
|
||||
`CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0,
|
||||
`CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE,
|
||||
`CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA,
|
||||
`CS_CMP_SEL_CFGA, /*CFGRAM0: */
|
||||
`CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0,
|
||||
`CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE,
|
||||
`CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA,
|
||||
`CS_CMP_SEL_CFGA, /*CFGRAM1: */
|
||||
`CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0,
|
||||
`CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE,
|
||||
`CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA,
|
||||
`CS_CMP_SEL_CFGA, /*CFGRAM2: */
|
||||
`CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0,
|
||||
`CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE,
|
||||
`CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA,
|
||||
`CS_CMP_SEL_CFGA, /*CFGRAM3: */
|
||||
`CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0,
|
||||
`CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE,
|
||||
`CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA,
|
||||
`CS_CMP_SEL_CFGA, /*CFGRAM4: */
|
||||
`CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0,
|
||||
`CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE,
|
||||
`CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA,
|
||||
`CS_CMP_SEL_CFGA, /*CFGRAM5: */
|
||||
`CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0,
|
||||
`CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE,
|
||||
`CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA,
|
||||
`CS_CMP_SEL_CFGA, /*CFGRAM6: */
|
||||
`CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0,
|
||||
`CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE,
|
||||
`CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA,
|
||||
`CS_CMP_SEL_CFGA, /*CFGRAM7: */
|
||||
8'hFF, 8'h00, /*CFG9: */
|
||||
8'hFF, 8'hFF, /*CFG11-10: */
|
||||
`SC_CMPB_A1_D1, `SC_CMPA_A1_D1, `SC_CI_B_ARITH,
|
||||
`SC_CI_A_ARITH, `SC_C1_MASK_DSBL, `SC_C0_MASK_DSBL,
|
||||
`SC_A_MASK_DSBL, `SC_DEF_SI_0, `SC_SI_B_DEFSI,
|
||||
`SC_SI_A_DEFSI, /*CFG13-12: */
|
||||
`SC_A0_SRC_PIN, `SC_SHIFT_SL, 1'h0,
|
||||
1'h0, `SC_FIFO1_BUS, `SC_FIFO0_ALU,
|
||||
`SC_MSB_DSBL, `SC_MSB_BIT0, `SC_MSB_NOCHN,
|
||||
`SC_FB_NOCHN, `SC_CMP1_NOCHN,
|
||||
`SC_CMP0_NOCHN, /*CFG15-14: */
|
||||
10'h00, `SC_FIFO_CLK__DP,`SC_FIFO_CAP_AX,
|
||||
`SC_FIFO_LEVEL,`SC_FIFO__SYNC,`SC_EXTCRC_DSBL,
|
||||
`SC_WRK16CAT_DSBL /*CFG17-16: */
|
||||
}
|
||||
)) dp(
|
||||
/* input */ .clk(clk),
|
||||
/* input [02:00] */ .cs_addr(3'b0), // Program counter
|
||||
/* input */ .route_si(1'b0), // Shift in
|
||||
/* input */ .route_ci(1'b0), // Carry in
|
||||
/* input */ .f0_load(load), // Load FIFO 0
|
||||
/* input */ .f1_load(1'b0), // Load FIFO 1
|
||||
/* input */ .d0_load(1'b0), // Load Data Register 0
|
||||
/* input */ .d1_load(1'b0), // Load Data Register 1
|
||||
/* output */ .ce0(), // Accumulator 0 = Data register 0
|
||||
/* output */ .cl0(), // Accumulator 0 < Data register 0
|
||||
/* output */ .z0(), // Accumulator 0 = 0
|
||||
/* output */ .ff0(), // Accumulator 0 = FF
|
||||
/* output */ .ce1(), // Accumulator [0|1] = Data register 1
|
||||
/* output */ .cl1(), // Accumulator [0|1] < Data register 1
|
||||
/* output */ .z1(), // Accumulator 1 = 0
|
||||
/* output */ .ff1(), // Accumulator 1 = FF
|
||||
/* output */ .ov_msb(), // Operation over flow
|
||||
/* output */ .co_msb(), // Carry out
|
||||
/* output */ .cmsb(), // Carry out
|
||||
/* output */ .so(), // Shift out
|
||||
/* output */ .f0_bus_stat(drq), // not empty
|
||||
/* output */ .f0_blk_stat(full),// full
|
||||
/* output */ .f1_bus_stat(), // FIFO 1 status to uP
|
||||
/* output */ .f1_blk_stat(), // FIFO 1 status to DP
|
||||
/* input */ .ci(1'b0), // Carry in from previous stage
|
||||
/* output */ .co(), // Carry out to next stage
|
||||
/* input */ .sir(1'b0), // Shift in from right side
|
||||
/* output */ .sor(), // Shift out to right side
|
||||
/* input */ .sil(1'b0), // Shift in from left side
|
||||
/* output */ .sol(), // Shift out to left side
|
||||
/* input */ .msbi(1'b0), // MSB chain in
|
||||
/* output */ .msbo(), // MSB chain out
|
||||
/* input [01:00] */ .cei(2'b0), // Compare equal in from prev stage
|
||||
/* output [01:00] */ .ceo(), // Compare equal out to next stage
|
||||
/* input [01:00] */ .cli(2'b0), // Compare less than in from prv stage
|
||||
/* output [01:00] */ .clo(), // Compare less than out to next stage
|
||||
/* input [01:00] */ .zi(2'b0), // Zero detect in from previous stage
|
||||
/* output [01:00] */ .zo(), // Zero detect out to next stage
|
||||
/* input [01:00] */ .fi(2'b0), // 0xFF detect in from previous stage
|
||||
/* output [01:00] */ .fo(), // 0xFF detect out to next stage
|
||||
/* input [01:00] */ .capi(2'b0), // Capture in from previous stage
|
||||
/* output [01:00] */ .capo(), // Capture out to next stage
|
||||
/* input */ .cfbi(1'b0), // CRC Feedback in from previous stage
|
||||
/* output */ .cfbo(), // CRC Feedback out to next stage
|
||||
/* input [07:00] */ .pi(pi), // Parallel data port
|
||||
/* output [07:00] */ .po() // Parallel data port
|
||||
);
|
||||
|
||||
//`#end` -- edit above this line, do not edit this line
|
||||
endmodule
|
||||
//`#start footer` -- edit after this line, do not edit this line
|
||||
//`#end` -- edit above this line, do not edit this line
|
||||
|
||||
|
||||
|
||||
|
||||
27
FluxEngine.cydsn/FIFOout/API/c.c
Normal file
27
FluxEngine.cydsn/FIFOout/API/c.c
Normal file
@@ -0,0 +1,27 @@
|
||||
#include "cyfitter_cfg.h"
|
||||
#include "cydevice_trm.h"
|
||||
#include "cyfitter.h"
|
||||
#include "`$INSTANCE_NAME`_h.h"
|
||||
|
||||
void `$INSTANCE_NAME`_Start()
|
||||
{
|
||||
`$INSTANCE_NAME`_Init();
|
||||
}
|
||||
|
||||
void `$INSTANCE_NAME`_Stop()
|
||||
{
|
||||
`$INSTANCE_NAME`_Disable();
|
||||
}
|
||||
|
||||
void `$INSTANCE_NAME`_Init()
|
||||
{
|
||||
`$INSTANCE_NAME`_Enable();
|
||||
|
||||
}
|
||||
void `$INSTANCE_NAME`_Enable()
|
||||
{
|
||||
}
|
||||
|
||||
void `$INSTANCE_NAME`_Disable()
|
||||
{
|
||||
}
|
||||
50
FluxEngine.cydsn/FIFOout/API/h.h
Normal file
50
FluxEngine.cydsn/FIFOout/API/h.h
Normal file
@@ -0,0 +1,50 @@
|
||||
#if !defined(`$INSTANCE_NAME`_H)
|
||||
#define `$INSTANCE_NAME`_H
|
||||
|
||||
#include "cytypes.h"
|
||||
#include "cyfitter.h"
|
||||
#include "CyLib.h"
|
||||
|
||||
#define `$INSTANCE_NAME`_FIFO_PTR ((reg8 *) `$INSTANCE_NAME`_dp__F0_REG)
|
||||
|
||||
/* Macros to clear DP FIFOs.*/
|
||||
#define `$INSTANCE_NAME`_CLEAR do { \
|
||||
CY_SET_XTND_REG8(\
|
||||
((reg8 *) `$INSTANCE_NAME`_dp__DP_AUX_CTL_REG), 0x01u | \
|
||||
CY_GET_XTND_REG8(((reg8 *) `$INSTANCE_NAME`_dp__DP_AUX_CTL_REG)));\
|
||||
CY_SET_XTND_REG8(\
|
||||
((reg8 *) `$INSTANCE_NAME`_dp__DP_AUX_CTL_REG), 0xfeu & \
|
||||
CY_GET_XTND_REG8(((reg8 *) `$INSTANCE_NAME`_dp__DP_AUX_CTL_REG)));\
|
||||
} while(0)
|
||||
|
||||
/* Macros to set FIFO level mode. See the TRM for details */
|
||||
#define `$INSTANCE_NAME`_SET_LEVEL_NORMAL \
|
||||
CY_SET_XTND_REG8(\
|
||||
((reg8 *) `$INSTANCE_NAME`_dp__DP_AUX_CTL_REG), 0xfbu & \
|
||||
CY_GET_XTND_REG8(((reg8 *) `$INSTANCE_NAME`_dp__DP_AUX_CTL_REG)))
|
||||
#define `$INSTANCE_NAME`_SET_LEVEL_MID \
|
||||
CY_SET_XTND_REG8(\
|
||||
((reg8 *) `$INSTANCE_NAME`_dp__DP_AUX_CTL_REG), 0x04u | \
|
||||
CY_GET_XTND_REG8(((reg8 *) `$INSTANCE_NAME`_dp__DP_AUX_CTL_REG)))
|
||||
|
||||
/* Macros to set FIFO to single-buffer mode. */
|
||||
#define `$INSTANCE_NAME`_SINGLE_BUFFER_SET \
|
||||
CY_SET_XTND_REG8(\
|
||||
((reg8 *) `$INSTANCE_NAME`_dp__DP_AUX_CTL_REG), 0x01u | \
|
||||
CY_GET_XTND_REG8(((reg8 *) `$INSTANCE_NAME`_dp__DP_AUX_CTL_REG)))
|
||||
|
||||
/* Macros to return the FIFO to normal mode. */
|
||||
#define `$INSTANCE_NAME`_SINGLE_BUFFER_UNSET \
|
||||
CY_SET_XTND_REG8(\
|
||||
((reg8 *) `$INSTANCE_NAME`_dp__DP_AUX_CTL_REG), 0xfeu & \
|
||||
CY_GET_XTND_REG8(((reg8 *) `$INSTANCE_NAME`_dp__DP_AUX_CTL_REG)))
|
||||
|
||||
void `$INSTANCE_NAME`_Enable();
|
||||
void `$INSTANCE_NAME`_Disable();
|
||||
void `$INSTANCE_NAME`_Start();
|
||||
void `$INSTANCE_NAME`_Stop();
|
||||
void `$INSTANCE_NAME`_Init();
|
||||
|
||||
#endif
|
||||
|
||||
/* [] END OF FILE */
|
||||
BIN
FluxEngine.cydsn/FIFOout/FIFOout.cysym
Normal file
BIN
FluxEngine.cydsn/FIFOout/FIFOout.cysym
Normal file
Binary file not shown.
169
FluxEngine.cydsn/FIFOout/FIFOout.v
Normal file
169
FluxEngine.cydsn/FIFOout/FIFOout.v
Normal file
@@ -0,0 +1,169 @@
|
||||
|
||||
//`#start header` -- edit after this line, do not edit this line
|
||||
`include "cypress.v"
|
||||
//`#end` -- edit above this line, do not edit this line
|
||||
// Generated on 11/16/2017 at 15:44
|
||||
// Component: FIFOout
|
||||
module FIFOout (
|
||||
input req,
|
||||
input clk,
|
||||
output [7:0] d,
|
||||
output drq,
|
||||
output empty,
|
||||
output ack
|
||||
);
|
||||
|
||||
//`#start body` -- edit after this line, do not edit this line
|
||||
|
||||
/* Reads from the FIFO are done based on the FIFO being not empty. */
|
||||
|
||||
wire [7:0] po;
|
||||
assign d = po;
|
||||
|
||||
localparam STATE_WAITFORREQ = 0;
|
||||
localparam STATE_READFROMFIFO = 1;
|
||||
localparam STATE_WAITFORNREQ = 2;
|
||||
|
||||
reg [1:0] state;
|
||||
wire readfromfifo;
|
||||
|
||||
assign ack = (state == STATE_WAITFORNREQ);
|
||||
assign readfromfifo = (state == STATE_READFROMFIFO);
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
case (state)
|
||||
/* opcode is not valid; req is low; wait for req to go high. */
|
||||
STATE_WAITFORREQ:
|
||||
begin
|
||||
if (!empty && req)
|
||||
state <= STATE_READFROMFIFO;
|
||||
end
|
||||
|
||||
/* Fetch a single value from the FIFO. */
|
||||
STATE_READFROMFIFO:
|
||||
state <= STATE_WAITFORNREQ;
|
||||
|
||||
/* opcode is valid; ack is high. Wait for req to go low. */
|
||||
STATE_WAITFORNREQ:
|
||||
if (!req)
|
||||
state <= STATE_WAITFORREQ;
|
||||
endcase
|
||||
end
|
||||
|
||||
cy_psoc3_dp #(.cy_dpconfig(
|
||||
{
|
||||
`CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0,
|
||||
`CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE,
|
||||
`CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA,
|
||||
`CS_CMP_SEL_CFGA, /*CFGRAM0: idle */
|
||||
`CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0,
|
||||
`CS_SHFT_OP_PASS, `CS_A0_SRC___F0, `CS_A1_SRC_NONE,
|
||||
`CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA,
|
||||
`CS_CMP_SEL_CFGA, /*CFGRAM1: read from fifo */
|
||||
`CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0,
|
||||
`CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE,
|
||||
`CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA,
|
||||
`CS_CMP_SEL_CFGA, /*CFGRAM2: */
|
||||
`CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0,
|
||||
`CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE,
|
||||
`CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA,
|
||||
`CS_CMP_SEL_CFGA, /*CFGRAM3: */
|
||||
`CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0,
|
||||
`CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE,
|
||||
`CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA,
|
||||
`CS_CMP_SEL_CFGA, /*CFGRAM4: */
|
||||
`CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0,
|
||||
`CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE,
|
||||
`CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA,
|
||||
`CS_CMP_SEL_CFGA, /*CFGRAM5: */
|
||||
`CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0,
|
||||
`CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE,
|
||||
`CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA,
|
||||
`CS_CMP_SEL_CFGA, /*CFGRAM6: */
|
||||
`CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0,
|
||||
`CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE,
|
||||
`CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA,
|
||||
`CS_CMP_SEL_CFGA, /*CFGRAM7: */
|
||||
8'hFF, 8'h00, /*CFG9: */
|
||||
8'hFF, 8'hFF, /*CFG11-10: */
|
||||
`SC_CMPB_A1_D1, `SC_CMPA_A1_D1, `SC_CI_B_ARITH,
|
||||
`SC_CI_A_ARITH, `SC_C1_MASK_DSBL, `SC_C0_MASK_DSBL,
|
||||
`SC_A_MASK_DSBL, `SC_DEF_SI_0, `SC_SI_B_DEFSI,
|
||||
`SC_SI_A_DEFSI, /*CFG13-12: */
|
||||
`SC_A0_SRC_ACC, `SC_SHIFT_SL, 1'h0,
|
||||
1'h0, `SC_FIFO1_BUS, `SC_FIFO0_BUS,
|
||||
`SC_MSB_DSBL, `SC_MSB_BIT0, `SC_MSB_NOCHN,
|
||||
`SC_FB_NOCHN, `SC_CMP1_NOCHN,
|
||||
`SC_CMP0_NOCHN, /*CFG15-14: */
|
||||
10'h00, `SC_FIFO_CLK__DP,`SC_FIFO_CAP_AX,
|
||||
`SC_FIFO_LEVEL,`SC_FIFO_ASYNC,`SC_EXTCRC_DSBL,
|
||||
`SC_WRK16CAT_DSBL /*CFG17-16: */
|
||||
}
|
||||
)) dp(
|
||||
/* input */ .reset(1'b0),
|
||||
/* input */ .clk(clk),
|
||||
/* input [02:00] */ .cs_addr({2'b0, readfromfifo}),
|
||||
/* input */ .route_si(1'b0),
|
||||
/* input */ .route_ci(1'b0),
|
||||
/* input */ .f0_load(1'b0),
|
||||
/* input */ .f1_load(1'b0),
|
||||
/* input */ .d0_load(1'b0),
|
||||
/* input */ .d1_load(1'b0),
|
||||
/* output */ .ce0(),
|
||||
/* output */ .cl0(),
|
||||
/* output */ .z0(),
|
||||
/* output */ .ff0(),
|
||||
/* output */ .ce1(),
|
||||
/* output */ .cl1(),
|
||||
/* output */ .z1(),
|
||||
/* output */ .ff1(),
|
||||
/* output */ .ov_msb(),
|
||||
/* output */ .co_msb(),
|
||||
/* output */ .cmsb(),
|
||||
/* output */ .so(),
|
||||
/* output */ .f0_bus_stat(drq), // not full
|
||||
/* output */ .f0_blk_stat(empty), // empty
|
||||
/* output */ .f1_bus_stat(),
|
||||
/* output */ .f1_blk_stat(),
|
||||
|
||||
/* input */ .ci(1'b0), // Carry in from previous stage
|
||||
/* output */ .co(),// Carry out to next stage
|
||||
/* input */ .sir(1'b0), // Shift in from right side
|
||||
/* output */ .sor(), // Shift out to right side
|
||||
/* input */ .sil(1'b0), // Shift in from left side
|
||||
/* output */ .sol(), // Shift out to left side
|
||||
/* input */ .msbi(1'b0), // MSB chain in
|
||||
/* output */ .msbo(), // MSB chain out
|
||||
/* input [01:00] */ .cei(2'b0), // Compare equal in from prev stage
|
||||
/* output [01:00] */ .ceo(), // Compare equal out to next stage
|
||||
/* input [01:00] */ .cli(2'b0), // Compare less than in from prv stage
|
||||
/* output [01:00] */ .clo(), // Compare less than out to next stage
|
||||
/* input [01:00] */ .zi(2'b0), // Zero detect in from previous stage
|
||||
/* output [01:00] */ .zo(), // Zero detect out to next stage
|
||||
/* input [01:00] */ .fi(2'b0), // 0xFF detect in from previous stage
|
||||
/* output [01:00] */ .fo(), // 0xFF detect out to next stage
|
||||
/* input [01:00] */ .capi(2'b0), // Software capture from previous stage
|
||||
/* output [01:00] */ .capo(), // Software capture to next stage
|
||||
/* input */ .cfbi(1'b0), // CRC Feedback in from previous stage
|
||||
/* output */ .cfbo(), // CRC Feedback out to next stage
|
||||
/* input [07:00] */ .pi(8'b0), // Parallel data port
|
||||
/* output [07:00] */ .po(po) // Parallel data port
|
||||
);
|
||||
|
||||
//`#end` -- edit above this line, do not edit this line
|
||||
endmodule
|
||||
//`#start footer` -- edit after this line, do not edit this line
|
||||
//`#end` -- edit above this line, do not edit this line
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -28,6 +28,54 @@
|
||||
<Data key="sync_with_bus_clk" value="True" />
|
||||
<Data key="user_set_domain" value="False" />
|
||||
</Group>
|
||||
<Group key="1a7e8637-3b6b-4e84-839c-0dfc18fdaf5b">
|
||||
<Data key="check_tolerance" value="True" />
|
||||
<Data key="clock_version" value="v1" />
|
||||
<Data key="derive_type" value="NAMED_DIVIDER" />
|
||||
<Data key="desired_freq" value="0" />
|
||||
<Data key="desired_unit" value="15" />
|
||||
<Data key="divider" value="0" />
|
||||
<Data key="domain" value="DIGITAL" />
|
||||
<Data key="enabled" value="True" />
|
||||
<Data key="minus_accuracy" value="0.25" />
|
||||
<Data key="minus_tolerance" value="5" />
|
||||
<Data key="name" value="Clock_5" />
|
||||
<Data key="named_src_direct_connect" value="True" />
|
||||
<Data key="netlist_name" value="Clock_5" />
|
||||
<Data key="placement" value="AUTO" />
|
||||
<Data key="plus_accuracy" value="0.25" />
|
||||
<Data key="plus_tolerance" value="5" />
|
||||
<Data key="scope" value="LOCAL" />
|
||||
<Data key="src_clk_id" value="75C2148C-3656-4d8a-846D-0CAE99AB6FF7" />
|
||||
<Data key="src_clk_name" value="BUS_CLK" />
|
||||
<Data key="start_on_reset" value="True" />
|
||||
<Data key="sync_with_bus_clk" value="True" />
|
||||
<Data key="user_set_domain" value="False" />
|
||||
</Group>
|
||||
<Group key="3f3708ae-fb62-4012-919b-9a3b9a1dfbc2">
|
||||
<Data key="check_tolerance" value="True" />
|
||||
<Data key="clock_version" value="v1" />
|
||||
<Data key="derive_type" value="NAMED_DIVIDER" />
|
||||
<Data key="desired_freq" value="0" />
|
||||
<Data key="desired_unit" value="15" />
|
||||
<Data key="divider" value="0" />
|
||||
<Data key="domain" value="DIGITAL" />
|
||||
<Data key="enabled" value="True" />
|
||||
<Data key="minus_accuracy" value="0.25" />
|
||||
<Data key="minus_tolerance" value="5" />
|
||||
<Data key="name" value="Clock_8" />
|
||||
<Data key="named_src_direct_connect" value="True" />
|
||||
<Data key="netlist_name" value="Clock_8" />
|
||||
<Data key="placement" value="AUTO" />
|
||||
<Data key="plus_accuracy" value="0.25" />
|
||||
<Data key="plus_tolerance" value="5" />
|
||||
<Data key="scope" value="LOCAL" />
|
||||
<Data key="src_clk_id" value="75C2148C-3656-4d8a-846D-0CAE99AB6FF7" />
|
||||
<Data key="src_clk_name" value="BUS_CLK" />
|
||||
<Data key="start_on_reset" value="True" />
|
||||
<Data key="sync_with_bus_clk" value="True" />
|
||||
<Data key="user_set_domain" value="False" />
|
||||
</Group>
|
||||
<Group key="4eef02b9-8ad1-43c4-85f1-b3335faa5fc4">
|
||||
<Data key="check_tolerance" value="True" />
|
||||
<Data key="clock_version" value="v1" />
|
||||
@@ -147,6 +195,54 @@
|
||||
<Data key="sync_with_bus_clk" value="True" />
|
||||
<Data key="user_set_domain" value="False" />
|
||||
</Group>
|
||||
<Group key="71bc291d-84a7-40a8-b7b2-1c8a34326a31">
|
||||
<Data key="check_tolerance" value="True" />
|
||||
<Data key="clock_version" value="v1" />
|
||||
<Data key="derive_type" value="NAMED_FREQ" />
|
||||
<Data key="desired_freq" value="300" />
|
||||
<Data key="desired_unit" value="0" />
|
||||
<Data key="divider" value="65536" />
|
||||
<Data key="domain" value="DIGITAL" />
|
||||
<Data key="enabled" value="True" />
|
||||
<Data key="minus_accuracy" value="0.25" />
|
||||
<Data key="minus_tolerance" value="5" />
|
||||
<Data key="name" value="CLOCK300" />
|
||||
<Data key="named_src_direct_connect" value="False" />
|
||||
<Data key="netlist_name" value="CLOCK300" />
|
||||
<Data key="placement" value="AUTO" />
|
||||
<Data key="plus_accuracy" value="0.25" />
|
||||
<Data key="plus_tolerance" value="5" />
|
||||
<Data key="scope" value="LOCAL" />
|
||||
<Data key="src_clk_id" value="CEF43CFB-0213-49b9-B980-2FFAB81C5B47" />
|
||||
<Data key="src_clk_name" value="IMO" />
|
||||
<Data key="start_on_reset" value="True" />
|
||||
<Data key="sync_with_bus_clk" value="True" />
|
||||
<Data key="user_set_domain" value="False" />
|
||||
</Group>
|
||||
<Group key="90ce0c72-9f10-44ef-a049-f0f525d59bea">
|
||||
<Data key="check_tolerance" value="True" />
|
||||
<Data key="clock_version" value="v1" />
|
||||
<Data key="derive_type" value="NAMED_FREQ" />
|
||||
<Data key="desired_freq" value="128" />
|
||||
<Data key="desired_unit" value="0" />
|
||||
<Data key="divider" value="65536" />
|
||||
<Data key="domain" value="DIGITAL" />
|
||||
<Data key="enabled" value="True" />
|
||||
<Data key="minus_accuracy" value="0.25" />
|
||||
<Data key="minus_tolerance" value="5" />
|
||||
<Data key="name" value="CLOCK8" />
|
||||
<Data key="named_src_direct_connect" value="False" />
|
||||
<Data key="netlist_name" value="CLOCK8" />
|
||||
<Data key="placement" value="AUTO" />
|
||||
<Data key="plus_accuracy" value="0.25" />
|
||||
<Data key="plus_tolerance" value="5" />
|
||||
<Data key="scope" value="LOCAL" />
|
||||
<Data key="src_clk_id" value="CEF43CFB-0213-49b9-B980-2FFAB81C5B47" />
|
||||
<Data key="src_clk_name" value="IMO" />
|
||||
<Data key="start_on_reset" value="True" />
|
||||
<Data key="sync_with_bus_clk" value="True" />
|
||||
<Data key="user_set_domain" value="False" />
|
||||
</Group>
|
||||
<Group key="349ffa20-8576-4ac3-9a6f-34ef606de6cf">
|
||||
<Data key="check_tolerance" value="True" />
|
||||
<Data key="clock_version" value="v1" />
|
||||
@@ -170,6 +266,29 @@
|
||||
<Data key="sync_with_bus_clk" value="True" />
|
||||
<Data key="user_set_domain" value="False" />
|
||||
</Group>
|
||||
<Group key="4033c29d-f4bc-4e94-ac95-aa587e869f88/696a0979-21fc-4185-bf38-6c79febcde7a">
|
||||
<Data key="check_tolerance" value="False" />
|
||||
<Data key="clock_version" value="v1" />
|
||||
<Data key="derive_type" value="AUTO" />
|
||||
<Data key="desired_freq" value="1600000" />
|
||||
<Data key="desired_unit" value="0" />
|
||||
<Data key="divider" value="40" />
|
||||
<Data key="domain" value="DIGITAL" />
|
||||
<Data key="enabled" value="True" />
|
||||
<Data key="minus_accuracy" value="0.25" />
|
||||
<Data key="minus_tolerance" value="5" />
|
||||
<Data key="name" value="OUTPUT_VOLTAGE_ADC_theACLK" />
|
||||
<Data key="netlist_name" value="\OUTPUT_VOLTAGE_ADC:theACLK\" />
|
||||
<Data key="placement" value="AUTO" />
|
||||
<Data key="plus_accuracy" value="0.25" />
|
||||
<Data key="plus_tolerance" value="5" />
|
||||
<Data key="scope" value="LOCAL" />
|
||||
<Data key="src_clk_id" value="61737EF6-3B74-48f9-8B91-F7473A442AE7" />
|
||||
<Data key="src_clk_name" value="MASTER_CLK" />
|
||||
<Data key="start_on_reset" value="True" />
|
||||
<Data key="sync_with_bus_clk" value="True" />
|
||||
<Data key="user_set_domain" value="False" />
|
||||
</Group>
|
||||
<Group key="6616e828-6611-4893-a674-66c861d79d6c">
|
||||
<Data key="check_tolerance" value="True" />
|
||||
<Data key="clock_version" value="v1" />
|
||||
@@ -241,6 +360,53 @@
|
||||
<Data key="sync_with_bus_clk" value="True" />
|
||||
<Data key="user_set_domain" value="False" />
|
||||
</Group>
|
||||
<Group key="09974428-e912-491f-8d2f-361ba50e7599">
|
||||
<Data key="check_tolerance" value="True" />
|
||||
<Data key="clock_version" value="v1" />
|
||||
<Data key="derive_type" value="NAMED_DIVIDER" />
|
||||
<Data key="desired_freq" value="0" />
|
||||
<Data key="desired_unit" value="15" />
|
||||
<Data key="divider" value="0" />
|
||||
<Data key="domain" value="DIGITAL" />
|
||||
<Data key="enabled" value="True" />
|
||||
<Data key="minus_accuracy" value="0.25" />
|
||||
<Data key="minus_tolerance" value="5" />
|
||||
<Data key="name" value="Clock_6" />
|
||||
<Data key="named_src_direct_connect" value="True" />
|
||||
<Data key="netlist_name" value="Clock_6" />
|
||||
<Data key="placement" value="AUTO" />
|
||||
<Data key="plus_accuracy" value="0.25" />
|
||||
<Data key="plus_tolerance" value="5" />
|
||||
<Data key="scope" value="LOCAL" />
|
||||
<Data key="src_clk_id" value="75C2148C-3656-4d8a-846D-0CAE99AB6FF7" />
|
||||
<Data key="src_clk_name" value="BUS_CLK" />
|
||||
<Data key="start_on_reset" value="True" />
|
||||
<Data key="sync_with_bus_clk" value="True" />
|
||||
<Data key="user_set_domain" value="False" />
|
||||
</Group>
|
||||
<Group key="a5825a94-fa18-4e4f-a843-bc687cacbd56/696a0979-21fc-4185-bf38-6c79febcde7a">
|
||||
<Data key="check_tolerance" value="False" />
|
||||
<Data key="clock_version" value="v1" />
|
||||
<Data key="derive_type" value="AUTO" />
|
||||
<Data key="desired_freq" value="1600000" />
|
||||
<Data key="desired_unit" value="0" />
|
||||
<Data key="divider" value="40" />
|
||||
<Data key="domain" value="DIGITAL" />
|
||||
<Data key="enabled" value="True" />
|
||||
<Data key="minus_accuracy" value="0.25" />
|
||||
<Data key="minus_tolerance" value="5" />
|
||||
<Data key="name" value="INPUT_VOLTAGE_ADC_theACLK" />
|
||||
<Data key="netlist_name" value="\INPUT_VOLTAGE_ADC:theACLK\" />
|
||||
<Data key="placement" value="AUTO" />
|
||||
<Data key="plus_accuracy" value="0.25" />
|
||||
<Data key="plus_tolerance" value="5" />
|
||||
<Data key="scope" value="LOCAL" />
|
||||
<Data key="src_clk_id" value="61737EF6-3B74-48f9-8B91-F7473A442AE7" />
|
||||
<Data key="src_clk_name" value="MASTER_CLK" />
|
||||
<Data key="start_on_reset" value="True" />
|
||||
<Data key="sync_with_bus_clk" value="True" />
|
||||
<Data key="user_set_domain" value="False" />
|
||||
</Group>
|
||||
<Group key="b762c287-7f87-4b21-982e-84be01dc5115">
|
||||
<Data key="check_tolerance" value="True" />
|
||||
<Data key="clock_version" value="v1" />
|
||||
@@ -288,6 +454,30 @@
|
||||
<Data key="sync_with_bus_clk" value="True" />
|
||||
<Data key="user_set_domain" value="False" />
|
||||
</Group>
|
||||
<Group key="b722443b-8f81-46dc-bf9b-c95eb62bc181">
|
||||
<Data key="check_tolerance" value="True" />
|
||||
<Data key="clock_version" value="v1" />
|
||||
<Data key="derive_type" value="NAMED_DIVIDER" />
|
||||
<Data key="desired_freq" value="0" />
|
||||
<Data key="desired_unit" value="15" />
|
||||
<Data key="divider" value="0" />
|
||||
<Data key="domain" value="DIGITAL" />
|
||||
<Data key="enabled" value="True" />
|
||||
<Data key="minus_accuracy" value="0.25" />
|
||||
<Data key="minus_tolerance" value="5" />
|
||||
<Data key="name" value="Clock_1" />
|
||||
<Data key="named_src_direct_connect" value="True" />
|
||||
<Data key="netlist_name" value="Clock_1" />
|
||||
<Data key="placement" value="AUTO" />
|
||||
<Data key="plus_accuracy" value="0.25" />
|
||||
<Data key="plus_tolerance" value="5" />
|
||||
<Data key="scope" value="LOCAL" />
|
||||
<Data key="src_clk_id" value="75C2148C-3656-4d8a-846D-0CAE99AB6FF7" />
|
||||
<Data key="src_clk_name" value="BUS_CLK" />
|
||||
<Data key="start_on_reset" value="True" />
|
||||
<Data key="sync_with_bus_clk" value="True" />
|
||||
<Data key="user_set_domain" value="False" />
|
||||
</Group>
|
||||
<Group key="cb7e877c-9fb4-4fc1-a708-f1e48eb5a68c">
|
||||
<Data key="check_tolerance" value="True" />
|
||||
<Data key="clock_version" value="v1" />
|
||||
@@ -312,6 +502,30 @@
|
||||
<Data key="sync_with_bus_clk" value="True" />
|
||||
<Data key="user_set_domain" value="False" />
|
||||
</Group>
|
||||
<Group key="d3075dc6-05c8-4dc9-9959-cf7014c0e66f">
|
||||
<Data key="check_tolerance" value="True" />
|
||||
<Data key="clock_version" value="v1" />
|
||||
<Data key="derive_type" value="NAMED_DIVIDER" />
|
||||
<Data key="desired_freq" value="0" />
|
||||
<Data key="desired_unit" value="15" />
|
||||
<Data key="divider" value="0" />
|
||||
<Data key="domain" value="DIGITAL" />
|
||||
<Data key="enabled" value="True" />
|
||||
<Data key="minus_accuracy" value="0.25" />
|
||||
<Data key="minus_tolerance" value="5" />
|
||||
<Data key="name" value="Clock_7" />
|
||||
<Data key="named_src_direct_connect" value="True" />
|
||||
<Data key="netlist_name" value="Clock_7" />
|
||||
<Data key="placement" value="AUTO" />
|
||||
<Data key="plus_accuracy" value="0.25" />
|
||||
<Data key="plus_tolerance" value="5" />
|
||||
<Data key="scope" value="LOCAL" />
|
||||
<Data key="src_clk_id" value="75C2148C-3656-4d8a-846D-0CAE99AB6FF7" />
|
||||
<Data key="src_clk_name" value="BUS_CLK" />
|
||||
<Data key="start_on_reset" value="True" />
|
||||
<Data key="sync_with_bus_clk" value="True" />
|
||||
<Data key="user_set_domain" value="False" />
|
||||
</Group>
|
||||
<Group key="e4a53a4c-40e1-4747-a72a-10193ffdf31c">
|
||||
<Data key="check_tolerance" value="True" />
|
||||
<Data key="clock_version" value="v1" />
|
||||
@@ -609,18 +823,27 @@
|
||||
<Group key="DWRInstGuidMapping">
|
||||
<Group key="Clock">
|
||||
<Data key="0b2f9bbb-00ce-4115-a788-ffb9d046a9e5" value="Clock_4" />
|
||||
<Data key="1a7e8637-3b6b-4e84-839c-0dfc18fdaf5b" value="Clock_5" />
|
||||
<Data key="3f3708ae-fb62-4012-919b-9a3b9a1dfbc2" value="Clock_8" />
|
||||
<Data key="4eef02b9-8ad1-43c4-85f1-b3335faa5fc4" value="Clock_3" />
|
||||
<Data key="06c4d5d4-f15f-4b29-a1d0-c24b2e38b1ec" value="CounterClock" />
|
||||
<Data key="24cd38f7-f472-4403-837f-86807c8f5333" value="PULSE_CLOCK" />
|
||||
<Data key="63ed4137-0b09-4256-8a27-35c9a2653f1a" value="Clock_2" />
|
||||
<Data key="66f14071-bddd-4b4d-a9aa-a129cceaa7b6" value="Clock_3" />
|
||||
<Data key="71bc291d-84a7-40a8-b7b2-1c8a34326a31" value="CLOCK300" />
|
||||
<Data key="90ce0c72-9f10-44ef-a049-f0f525d59bea" value="CLOCK8" />
|
||||
<Data key="349ffa20-8576-4ac3-9a6f-34ef606de6cf" value="Clock_1" />
|
||||
<Data key="4033c29d-f4bc-4e94-ac95-aa587e869f88/696a0979-21fc-4185-bf38-6c79febcde7a" value="OUTPUT_VOLTAGE_ADC_theACLK" />
|
||||
<Data key="6616e828-6611-4893-a674-66c861d79d6c" value="SignalSamplingClock" />
|
||||
<Data key="12664fc6-9d70-44b1-8a49-887a292e1b7f" value="Clock_3" />
|
||||
<Data key="75187c05-9501-4450-b306-6ccdd3bb77db" value="Clock_5" />
|
||||
<Data key="09974428-e912-491f-8d2f-361ba50e7599" value="Clock_6" />
|
||||
<Data key="a5825a94-fa18-4e4f-a843-bc687cacbd56/696a0979-21fc-4185-bf38-6c79febcde7a" value="INPUT_VOLTAGE_ADC_theACLK" />
|
||||
<Data key="b762c287-7f87-4b21-982e-84be01dc5115" value="Clock_2" />
|
||||
<Data key="b0162966-0060-4af5-82d1-fcb491ad7619/be0a0e37-ad17-42ca-b5a1-1a654d736358" value="UART_IntClock" />
|
||||
<Data key="b722443b-8f81-46dc-bf9b-c95eb62bc181" value="Clock_1" />
|
||||
<Data key="cb7e877c-9fb4-4fc1-a708-f1e48eb5a68c" value="CounterClock" />
|
||||
<Data key="d3075dc6-05c8-4dc9-9959-cf7014c0e66f" value="Clock_7" />
|
||||
<Data key="e4a53a4c-40e1-4747-a72a-10193ffdf31c" value="Clock_1" />
|
||||
<Data key="efd5f185-0c32-4824-ba72-3ceb5356f5a7" value="Clock_1" />
|
||||
</Group>
|
||||
@@ -628,6 +851,7 @@
|
||||
<Data key="4a398466-709f-4228-9500-96178658e13e" value="RDATA" />
|
||||
<Data key="5a3407c1-b434-4438-a7b4-b9dfd2280495" value="MOTEA" />
|
||||
<Data key="8d318d8b-cf7b-4b6b-b02c-ab1c5c49d0ba" value="SW1" />
|
||||
<Data key="8fc20a4f-e4d1-44b3-a5d4-546e8628d61e" value="LED" />
|
||||
<Data key="12e00eac-69b5-4717-85c8-25ef6b224d4c" value="DEBUG_PINS" />
|
||||
<Data key="41e2d8ed-5494-4d8c-8ff7-f4f789cece51" value="REDWC" />
|
||||
<Data key="264be2d3-9481-494b-8d9c-c1905a45e9cc" value="FDD" />
|
||||
@@ -638,16 +862,18 @@
|
||||
<Data key="a5d987c6-e45b-45b9-ad93-656fab06d720" value="TRK00" />
|
||||
<Data key="a93ef5b3-00f4-42c0-8fad-0e275a7e2537" value="MOTEB" />
|
||||
<Data key="b8380fb7-fdb8-449f-bd8d-c4ca96cdf55a" value="DEBUG_PINS" />
|
||||
<Data key="bc2e8987-db82-469c-bf6f-22fd3464cc70" value="DEBUG_PINS" />
|
||||
<Data key="bc5d52a1-1b25-4aa0-9ba9-3f81d122772f" value="DEBUG_PINS" />
|
||||
<Data key="beca5e2d-f70f-4900-a4db-7eca1ed3126e/8b77a6c4-10a0-4390-971c-672353e2a49c" value="USBFS_Dm" />
|
||||
<Data key="beca5e2d-f70f-4900-a4db-7eca1ed3126e/618a72fc-5ddd-4df5-958f-a3d55102db42" value="USBFS_Dp" />
|
||||
<Data key="c5367cde-21d5-4866-9a32-d16abfea0c61" value="WPT" />
|
||||
<Data key="d19368c5-6855-41bb-a9ff-808938abef00" value="INDEX" />
|
||||
<Data key="e9f14b5a-b2bf-49b8-98f3-d7b5a43ace8d" value="DRVSB" />
|
||||
<Data key="e851a3b9-efb8-48be-bbb8-b303b216c393" value="LED" />
|
||||
<Data key="e851a3b9-efb8-48be-bbb8-b303b216c393" value="INDEX300" />
|
||||
<Data key="e51063a9-4fad-40c7-a06b-7cc4b137dc18" value="DSKCHG" />
|
||||
<Data key="ea7ee228-8b3f-426c-8bb8-cd7a81937769" value="DIR" />
|
||||
<Data key="ed092b9b-d398-4703-be89-cebf998501f6" value="UartTx" />
|
||||
<Data key="f9a7371a-8a7d-4144-8b08-69e3d2a3a663" value="INDEX360" />
|
||||
<Data key="fbd1f839-40f9-498e-a48b-5f3048ea5c3d/52f31aa9-2f0a-497d-9a1f-1424095e13e6" value="UART_tx" />
|
||||
<Data key="fede1767-f3fd-4021-b3d7-8f9d88f36f9b" value="DRVSA" />
|
||||
<Data key="fff78075-035e-43d7-8577-bc5be4d21926" value="WGATE" />
|
||||
@@ -3752,6 +3978,11 @@
|
||||
<Data key="Port Format" value="2,2" />
|
||||
</Group>
|
||||
</Group>
|
||||
<Group key="8fc20a4f-e4d1-44b3-a5d4-546e8628d61e">
|
||||
<Group key="0">
|
||||
<Data key="Port Format" value="2,1" />
|
||||
</Group>
|
||||
</Group>
|
||||
<Group key="12e00eac-69b5-4717-85c8-25ef6b224d4c">
|
||||
<Group key="0">
|
||||
<Data key="Port Format" value="2,2" />
|
||||
@@ -3859,6 +4090,32 @@
|
||||
<Data key="Port Format" value="2,3" />
|
||||
</Group>
|
||||
</Group>
|
||||
<Group key="bc2e8987-db82-469c-bf6f-22fd3464cc70">
|
||||
<Group key="0">
|
||||
<Data key="Port Format" value="0,0" />
|
||||
</Group>
|
||||
<Group key="1">
|
||||
<Data key="Port Format" value="0,1" />
|
||||
</Group>
|
||||
<Group key="2">
|
||||
<Data key="Port Format" value="0,2" />
|
||||
</Group>
|
||||
<Group key="3">
|
||||
<Data key="Port Format" value="0,3" />
|
||||
</Group>
|
||||
<Group key="4">
|
||||
<Data key="Port Format" value="0,4" />
|
||||
</Group>
|
||||
<Group key="5">
|
||||
<Data key="Port Format" value="0,5" />
|
||||
</Group>
|
||||
<Group key="6">
|
||||
<Data key="Port Format" value="0,6" />
|
||||
</Group>
|
||||
<Group key="7">
|
||||
<Data key="Port Format" value="0,7" />
|
||||
</Group>
|
||||
</Group>
|
||||
<Group key="bc5d52a1-1b25-4aa0-9ba9-3f81d122772f">
|
||||
<Group key="0">
|
||||
<Data key="Port Format" value="0,5" />
|
||||
@@ -3894,7 +4151,7 @@
|
||||
</Group>
|
||||
<Group key="e851a3b9-efb8-48be-bbb8-b303b216c393">
|
||||
<Group key="0">
|
||||
<Data key="Port Format" value="2,1" />
|
||||
<Data key="Port Format" value="3,0" />
|
||||
</Group>
|
||||
</Group>
|
||||
<Group key="e51063a9-4fad-40c7-a06b-7cc4b137dc18">
|
||||
@@ -3912,9 +4169,14 @@
|
||||
<Data key="Port Format" value="12,7" />
|
||||
</Group>
|
||||
</Group>
|
||||
<Group key="f9a7371a-8a7d-4144-8b08-69e3d2a3a663">
|
||||
<Group key="0">
|
||||
<Data key="Port Format" value="3,1" />
|
||||
</Group>
|
||||
</Group>
|
||||
<Group key="fbd1f839-40f9-498e-a48b-5f3048ea5c3d/52f31aa9-2f0a-497d-9a1f-1424095e13e6">
|
||||
<Group key="0">
|
||||
<Data key="Port Format" value="2,5" />
|
||||
<Data key="Port Format" value="12,7" />
|
||||
</Group>
|
||||
</Group>
|
||||
<Group key="fede1767-f3fd-4021-b3d7-8f9d88f36f9b">
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
111
FluxEngine.cydsn/Sampler/Sampler.v
Normal file
111
FluxEngine.cydsn/Sampler/Sampler.v
Normal file
@@ -0,0 +1,111 @@
|
||||
|
||||
//`#start header` -- edit after this line, do not edit this line
|
||||
`include "cypress.v"
|
||||
`include "../SuperCounter/SuperCounter.v"
|
||||
|
||||
//`#end` -- edit above this line, do not edit this line
|
||||
// Generated on 12/11/2019 at 21:18
|
||||
// Component: Sampler
|
||||
module Sampler (
|
||||
output [2:0] debug_state,
|
||||
output reg [7:0] opcode,
|
||||
output req,
|
||||
input clock,
|
||||
input index,
|
||||
input rdata,
|
||||
input reset,
|
||||
input sampleclock
|
||||
);
|
||||
|
||||
//`#start body` -- edit after this line, do not edit this line
|
||||
|
||||
localparam STATE_RESET = 0;
|
||||
localparam STATE_WAITING = 1;
|
||||
localparam STATE_OPCODE = 2;
|
||||
|
||||
reg [1:0] state;
|
||||
reg [6:0] counter;
|
||||
|
||||
reg oldsampleclock;
|
||||
wire sampleclocked;
|
||||
assign sampleclocked = !oldsampleclock && sampleclock;
|
||||
|
||||
reg oldindex;
|
||||
wire indexed;
|
||||
assign indexed = !oldindex && index;
|
||||
|
||||
wire rdataed;
|
||||
reg oldrdata;
|
||||
assign rdataed = !oldrdata && rdata;
|
||||
|
||||
assign req = (state == STATE_OPCODE);
|
||||
|
||||
always @(posedge clock)
|
||||
begin
|
||||
if (reset)
|
||||
begin
|
||||
state <= STATE_RESET;
|
||||
opcode <= 0;
|
||||
oldsampleclock <= 0;
|
||||
oldindex <= 0;
|
||||
oldrdata <= 0;
|
||||
counter <= 0;
|
||||
end
|
||||
else
|
||||
case (state)
|
||||
STATE_RESET:
|
||||
state <= STATE_WAITING;
|
||||
|
||||
STATE_WAITING:
|
||||
begin
|
||||
/* If something has happened, emit any necessary interval byte. */
|
||||
if ((rdataed || indexed) && (counter != 0))
|
||||
begin
|
||||
opcode <= {0, counter};
|
||||
state <= STATE_OPCODE;
|
||||
end
|
||||
else if (indexed)
|
||||
begin
|
||||
oldindex <= 1;
|
||||
opcode <= 8'h81;
|
||||
state <= STATE_OPCODE;
|
||||
end
|
||||
else if (rdataed)
|
||||
begin
|
||||
oldrdata <= 1;
|
||||
opcode <= 8'h80;
|
||||
state <= STATE_OPCODE;
|
||||
end
|
||||
else if (sampleclocked)
|
||||
begin
|
||||
oldsampleclock <= 1;
|
||||
if (counter == 7'h7f)
|
||||
begin
|
||||
opcode <= {0, counter};
|
||||
state <= STATE_OPCODE;
|
||||
end
|
||||
counter <= counter + 1;
|
||||
end
|
||||
|
||||
/* Reset state once we've done the thing. */
|
||||
|
||||
if (oldrdata && !rdata)
|
||||
oldrdata <= 0;
|
||||
if (oldindex && !index)
|
||||
oldindex <= 0;
|
||||
if (oldsampleclock && !sampleclock)
|
||||
oldsampleclock <= 0;
|
||||
end
|
||||
|
||||
STATE_OPCODE: /* opcode or interval byte sent here */
|
||||
begin
|
||||
state <= STATE_WAITING;
|
||||
counter <= 0;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
//`#end` -- edit above this line, do not edit this line
|
||||
endmodule
|
||||
//`#start footer` -- edit after this line, do not edit this line
|
||||
//`#end` -- edit above this line, do not edit this line
|
||||
Binary file not shown.
105
FluxEngine.cydsn/Sequencer/Sequencer.v
Normal file
105
FluxEngine.cydsn/Sequencer/Sequencer.v
Normal file
@@ -0,0 +1,105 @@
|
||||
|
||||
//`#start header` -- edit after this line, do not edit this line
|
||||
`include "cypress.v"
|
||||
//`#end` -- edit above this line, do not edit this line
|
||||
// Generated on 11/24/2019 at 17:25
|
||||
// Component: Sequencer
|
||||
module Sequencer (
|
||||
output req, /* request new data on leading edge */
|
||||
output wdata,
|
||||
output [2:0] debug_state,
|
||||
input clock,
|
||||
input dataclock, /* incoming data on leading edge */
|
||||
input [7:0] opcode,
|
||||
input index,
|
||||
input sampleclock,
|
||||
input reset
|
||||
);
|
||||
|
||||
//`#start body` -- edit after this line, do not edit this line
|
||||
|
||||
localparam STATE_LOAD = 0;
|
||||
localparam STATE_WAITING = 1;
|
||||
localparam STATE_PULSING = 2;
|
||||
localparam STATE_INDEXING = 3;
|
||||
|
||||
localparam OPCODE_PULSE = 8'h80;
|
||||
localparam OPCODE_INDEX = 8'h81;
|
||||
|
||||
reg [1:0] state;
|
||||
reg [6:0] countdown;
|
||||
|
||||
assign req = (!reset && (state == STATE_LOAD));
|
||||
assign wdata = (state == STATE_PULSING);
|
||||
assign debug_state = state;
|
||||
|
||||
reg olddataclock;
|
||||
wire dataclocked;
|
||||
always @(posedge clock) olddataclock <= dataclock;
|
||||
assign dataclocked = !olddataclock && dataclock;
|
||||
|
||||
reg oldsampleclock;
|
||||
reg sampleclocked;
|
||||
|
||||
reg oldindex;
|
||||
wire indexed;
|
||||
always @(posedge clock) oldindex <= index;
|
||||
assign indexed = !oldindex && index;
|
||||
|
||||
always @(posedge clock)
|
||||
begin
|
||||
if (reset)
|
||||
begin
|
||||
state <= STATE_LOAD;
|
||||
countdown <= 0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if (!oldsampleclock && sampleclock)
|
||||
sampleclocked <= 1;
|
||||
oldsampleclock <= sampleclock;
|
||||
|
||||
case (state)
|
||||
STATE_LOAD:
|
||||
/* Wait for a posedge on dataclocked, indicating an opcode has
|
||||
* arrived. */
|
||||
if (dataclocked)
|
||||
case (opcode)
|
||||
OPCODE_PULSE:
|
||||
state <= STATE_PULSING;
|
||||
|
||||
OPCODE_INDEX:
|
||||
state <= STATE_INDEXING;
|
||||
|
||||
default:
|
||||
begin
|
||||
countdown <= opcode[6:0];
|
||||
state <= STATE_WAITING;
|
||||
end
|
||||
endcase
|
||||
|
||||
STATE_WAITING:
|
||||
if (sampleclocked)
|
||||
begin
|
||||
sampleclocked <= 0;
|
||||
countdown <= countdown - 1;
|
||||
/* Nasty fudge factor here to account for one to two
|
||||
* sample ticks lost per pulse. */
|
||||
if (countdown <= 2)
|
||||
state <= STATE_LOAD;
|
||||
end
|
||||
|
||||
STATE_PULSING:
|
||||
state <= STATE_LOAD;
|
||||
|
||||
STATE_INDEXING:
|
||||
if (indexed)
|
||||
state <= STATE_LOAD;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
//`#end` -- edit above this line, do not edit this line
|
||||
endmodule
|
||||
//`#start footer` -- edit after this line, do not edit this line
|
||||
//`#end` -- edit above this line, do not edit this line
|
||||
BIN
FluxEngine.cydsn/SuperCounter/SuperCounter.cysym
Normal file
BIN
FluxEngine.cydsn/SuperCounter/SuperCounter.cysym
Normal file
Binary file not shown.
156
FluxEngine.cydsn/SuperCounter/SuperCounter.v
Normal file
156
FluxEngine.cydsn/SuperCounter/SuperCounter.v
Normal file
@@ -0,0 +1,156 @@
|
||||
|
||||
//`#start header` -- edit after this line, do not edit this line
|
||||
`include "cypress.v"
|
||||
//`#end` -- edit above this line, do not edit this line
|
||||
// Generated on 11/16/2017 at 15:44
|
||||
// Component: FIFOout
|
||||
module SuperCounter (
|
||||
input clk,
|
||||
input reset,
|
||||
input count,
|
||||
output [7:0] d,
|
||||
output drq,
|
||||
output empty,
|
||||
output ack
|
||||
);
|
||||
|
||||
//`#start body` -- edit after this line, do not edit this line
|
||||
|
||||
parameter ResetValue = 0;
|
||||
parameter Delta = 1;
|
||||
|
||||
wire [7:0] po;
|
||||
assign d = po;
|
||||
|
||||
localparam STATE_RESET = 0;
|
||||
localparam STATE_WAIT = 1;
|
||||
localparam STATE_ADD = 2;
|
||||
|
||||
reg oldcount;
|
||||
wire counted;
|
||||
assign counted = count && !oldcount;
|
||||
|
||||
always @(posedge clk) oldcount <= count;
|
||||
|
||||
wire [2:0] cs;
|
||||
assign cs = reset ? STATE_RESET : (counted ? STATE_ADD : STATE_WAIT);
|
||||
|
||||
cy_psoc3_dp #(.d0_init(ResetValue), .d1_init(Delta),
|
||||
.cy_dpconfig(
|
||||
{
|
||||
`CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0,
|
||||
`CS_SHFT_OP_PASS, `CS_A0_SRC___D0, `CS_A1_SRC_NONE,
|
||||
`CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA,
|
||||
`CS_CMP_SEL_CFGA, /*CFGRAM0: STATE_RESET*/
|
||||
`CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0,
|
||||
`CS_SHFT_OP_PASS, `CS_A0_SRC__ALU, `CS_A1_SRC_NONE,
|
||||
`CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA,
|
||||
`CS_CMP_SEL_CFGA, /*CFGRAM1: STATE_WAIT*/
|
||||
`CS_ALU_OP__ADD, `CS_SRCA_A0, `CS_SRCB_D1,
|
||||
`CS_SHFT_OP_PASS, `CS_A0_SRC__ALU, `CS_A1_SRC_NONE,
|
||||
`CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA,
|
||||
`CS_CMP_SEL_CFGA, /*CFGRAM2: STATE_ADD*/
|
||||
`CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0,
|
||||
`CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE,
|
||||
`CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA,
|
||||
`CS_CMP_SEL_CFGA, /*CFGRAM3: */
|
||||
`CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0,
|
||||
`CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE,
|
||||
`CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA,
|
||||
`CS_CMP_SEL_CFGA, /*CFGRAM4: */
|
||||
`CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0,
|
||||
`CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE,
|
||||
`CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA,
|
||||
`CS_CMP_SEL_CFGA, /*CFGRAM5: */
|
||||
`CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0,
|
||||
`CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE,
|
||||
`CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA,
|
||||
`CS_CMP_SEL_CFGA, /*CFGRAM6: */
|
||||
`CS_ALU_OP_PASS, `CS_SRCA_A0, `CS_SRCB_D0,
|
||||
`CS_SHFT_OP_PASS, `CS_A0_SRC_NONE, `CS_A1_SRC_NONE,
|
||||
`CS_FEEDBACK_DSBL, `CS_CI_SEL_CFGA, `CS_SI_SEL_CFGA,
|
||||
`CS_CMP_SEL_CFGA, /*CFGRAM7: */
|
||||
8'hFF, 8'h00, /*CFG9: */
|
||||
8'hFF, 8'hFF, /*CFG11-10: */
|
||||
`SC_CMPB_A1_D1, `SC_CMPA_A1_D1, `SC_CI_B_ARITH,
|
||||
`SC_CI_A_ARITH, `SC_C1_MASK_DSBL, `SC_C0_MASK_DSBL,
|
||||
`SC_A_MASK_DSBL, `SC_DEF_SI_0, `SC_SI_B_DEFSI,
|
||||
`SC_SI_A_DEFSI, /*CFG13-12: */
|
||||
`SC_A0_SRC_ACC, `SC_SHIFT_SL, 1'h0,
|
||||
1'h0, `SC_FIFO1_BUS, `SC_FIFO0_BUS,
|
||||
`SC_MSB_DSBL, `SC_MSB_BIT0, `SC_MSB_NOCHN,
|
||||
`SC_FB_NOCHN, `SC_CMP1_NOCHN,
|
||||
`SC_CMP0_NOCHN, /*CFG15-14: */
|
||||
10'h00, `SC_FIFO_CLK__DP,`SC_FIFO_CAP_AX,
|
||||
`SC_FIFO_LEVEL,`SC_FIFO_ASYNC,`SC_EXTCRC_DSBL,
|
||||
`SC_WRK16CAT_DSBL /*CFG17-16: */
|
||||
}
|
||||
)) dp(
|
||||
/* input */ .reset(1'b0),
|
||||
/* input */ .clk(clk),
|
||||
/* input [02:00] */ .cs_addr(cs),
|
||||
/* input */ .route_si(1'b0),
|
||||
/* input */ .route_ci(1'b0),
|
||||
/* input */ .f0_load(1'b0),
|
||||
/* input */ .f1_load(1'b0),
|
||||
/* input */ .d0_load(1'b0),
|
||||
/* input */ .d1_load(1'b0),
|
||||
/* output */ .ce0(),
|
||||
/* output */ .cl0(),
|
||||
/* output */ .z0(),
|
||||
/* output */ .ff0(),
|
||||
/* output */ .ce1(),
|
||||
/* output */ .cl1(),
|
||||
/* output */ .z1(),
|
||||
/* output */ .ff1(),
|
||||
/* output */ .ov_msb(),
|
||||
/* output */ .co_msb(),
|
||||
/* output */ .cmsb(),
|
||||
/* output */ .so(),
|
||||
/* output */ .f0_bus_stat(),
|
||||
/* output */ .f0_blk_stat(),
|
||||
/* output */ .f1_bus_stat(),
|
||||
/* output */ .f1_blk_stat(),
|
||||
|
||||
/* input */ .ci(1'b0), // Carry in from previous stage
|
||||
/* output */ .co(),// Carry out to next stage
|
||||
/* input */ .sir(1'b0), // Shift in from right side
|
||||
/* output */ .sor(), // Shift out to right side
|
||||
/* input */ .sil(1'b0), // Shift in from left side
|
||||
/* output */ .sol(), // Shift out to left side
|
||||
/* input */ .msbi(1'b0), // MSB chain in
|
||||
/* output */ .msbo(), // MSB chain out
|
||||
/* input [01:00] */ .cei(2'b0), // Compare equal in from prev stage
|
||||
/* output [01:00] */ .ceo(), // Compare equal out to next stage
|
||||
/* input [01:00] */ .cli(2'b0), // Compare less than in from prv stage
|
||||
/* output [01:00] */ .clo(), // Compare less than out to next stage
|
||||
/* input [01:00] */ .zi(2'b0), // Zero detect in from previous stage
|
||||
/* output [01:00] */ .zo(), // Zero detect out to next stage
|
||||
/* input [01:00] */ .fi(2'b0), // 0xFF detect in from previous stage
|
||||
/* output [01:00] */ .fo(), // 0xFF detect out to next stage
|
||||
/* input [01:00] */ .capi(2'b0), // Software capture from previous stage
|
||||
/* output [01:00] */ .capo(), // Software capture to next stage
|
||||
/* input */ .cfbi(1'b0), // CRC Feedback in from previous stage
|
||||
/* output */ .cfbo(), // CRC Feedback out to next stage
|
||||
/* input [07:00] */ .pi(8'b0), // Parallel data port
|
||||
/* output [07:00] */ .po(po) // Parallel data port
|
||||
);
|
||||
|
||||
//`#end` -- edit above this line, do not edit this line
|
||||
endmodule
|
||||
//`#start footer` -- edit after this line, do not edit this line
|
||||
//`#end` -- edit above this line, do not edit this line
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -17,20 +17,24 @@
|
||||
#define STEP_TOWARDS0 1
|
||||
#define STEP_AWAYFROM0 0
|
||||
|
||||
static volatile uint32_t clock = 0;
|
||||
static bool drive0_present;
|
||||
static bool drive1_present;
|
||||
|
||||
static volatile uint32_t clock = 0; /* ms */
|
||||
static volatile bool index_irq = false;
|
||||
|
||||
static bool motor_on = false;
|
||||
static uint32_t motor_on_time = 0;
|
||||
static bool homed = false;
|
||||
static int current_track = 0;
|
||||
static uint8_t current_drive_flags = 0;
|
||||
static struct set_drive_frame current_drive_flags;
|
||||
|
||||
#define BUFFER_COUNT 16
|
||||
#define BUFFER_COUNT 64 /* the maximum */
|
||||
#define BUFFER_SIZE 64
|
||||
static uint8_t td[BUFFER_COUNT];
|
||||
static uint8_t dma_buffer[BUFFER_COUNT][BUFFER_SIZE] __attribute__((aligned()));
|
||||
static uint8_t usb_buffer[BUFFER_SIZE] __attribute__((aligned()));
|
||||
static uint8_t xfer_buffer[BUFFER_SIZE] __attribute__((aligned()));
|
||||
static uint8_t dma_channel;
|
||||
#define NEXT_BUFFER(b) (((b)+1) % BUFFER_COUNT)
|
||||
|
||||
@@ -41,10 +45,27 @@ static volatile bool dma_underrun = false;
|
||||
#define DECLARE_REPLY_FRAME(STRUCT, TYPE) \
|
||||
STRUCT r = {.f = { .type = TYPE, .size = sizeof(STRUCT) }}
|
||||
|
||||
static void stop_motor(void);
|
||||
|
||||
static void system_timer_cb(void)
|
||||
{
|
||||
CyGlobalIntDisable;
|
||||
clock++;
|
||||
|
||||
static int counter300rpm = 0;
|
||||
counter300rpm++;
|
||||
if (counter300rpm == 200)
|
||||
counter300rpm = 0;
|
||||
|
||||
static int counter360rpm = 0;
|
||||
counter360rpm++;
|
||||
if (counter360rpm == 167)
|
||||
counter360rpm = 0;
|
||||
|
||||
FAKE_INDEX_GENERATOR_REG_Write(
|
||||
((counter300rpm == 0) ? 1 : 0)
|
||||
| ((counter360rpm == 0) ? 2 : 0));
|
||||
|
||||
CyGlobalIntEnable;
|
||||
}
|
||||
|
||||
@@ -85,10 +106,25 @@ static void print(const char* msg, ...)
|
||||
UART_PutCRLF();
|
||||
}
|
||||
|
||||
static void set_drive_flags(struct set_drive_frame* flags)
|
||||
{
|
||||
if (current_drive_flags.drive != flags->drive)
|
||||
{
|
||||
stop_motor();
|
||||
homed = false;
|
||||
}
|
||||
|
||||
current_drive_flags = *flags;
|
||||
DRIVESELECT_REG_Write(flags->drive ? 2 : 1); /* select drive 1 or 0 */
|
||||
DENSITY_REG_Write(flags->high_density); /* density bit */
|
||||
INDEX_REG_Write(flags->index_mode);
|
||||
}
|
||||
|
||||
static void start_motor(void)
|
||||
{
|
||||
if (!motor_on)
|
||||
{
|
||||
set_drive_flags(¤t_drive_flags);
|
||||
MOTOR_REG_Write(1);
|
||||
CyDelay(1000);
|
||||
homed = false;
|
||||
@@ -99,6 +135,16 @@ static void start_motor(void)
|
||||
CyWdtClear();
|
||||
}
|
||||
|
||||
static void stop_motor(void)
|
||||
{
|
||||
if (motor_on)
|
||||
{
|
||||
MOTOR_REG_Write(0);
|
||||
DRIVESELECT_REG_Write(0); /* deselect all drives */
|
||||
motor_on = false;
|
||||
}
|
||||
}
|
||||
|
||||
static void wait_until_writeable(int ep)
|
||||
{
|
||||
while (USBFS_GetEPState(ep) != USBFS_IN_BUFFER_EMPTY)
|
||||
@@ -138,25 +184,36 @@ static void cmd_get_version(struct any_frame* f)
|
||||
|
||||
static void step(int dir)
|
||||
{
|
||||
STEP_REG_Write(dir);
|
||||
CyDelayUs(1);
|
||||
STEP_REG_Write(dir | 2);
|
||||
CyDelayUs(1);
|
||||
STEP_REG_Write(dir);
|
||||
STEP_REG_Write(dir); /* step high */
|
||||
CyDelayUs(6);
|
||||
STEP_REG_Write(dir | 2); /* step low */
|
||||
CyDelayUs(6);
|
||||
STEP_REG_Write(dir); /* step high again, drive moves now */
|
||||
CyDelay(STEP_INTERVAL_TIME);
|
||||
}
|
||||
|
||||
/* returns true if it looks like a drive is attached */
|
||||
static bool home(void)
|
||||
{
|
||||
for (int i=0; i<100; i++)
|
||||
{
|
||||
/* Don't keep stepping forever, because if a drive's
|
||||
* not connected bad things happen. */
|
||||
if (TRACK0_REG_Read())
|
||||
return true;
|
||||
step(STEP_TOWARDS0);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void seek_to(int track)
|
||||
{
|
||||
start_motor();
|
||||
if (!homed)
|
||||
if (!homed || (track == 0))
|
||||
{
|
||||
print("homing");
|
||||
while (!TRACK0_REG_Read())
|
||||
step(STEP_TOWARDS0);
|
||||
|
||||
/* Step to -1, which should be a nop, to reset the disk on disk change. */
|
||||
step(STEP_TOWARDS0);
|
||||
home();
|
||||
|
||||
homed = true;
|
||||
current_track = 0;
|
||||
@@ -167,11 +224,7 @@ static void seek_to(int track)
|
||||
while (track != current_track)
|
||||
{
|
||||
if (TRACK0_REG_Read())
|
||||
{
|
||||
if (current_track != 0)
|
||||
print("unexpectedly detected track 0");
|
||||
current_track = 0;
|
||||
}
|
||||
|
||||
if (track > current_track)
|
||||
{
|
||||
@@ -208,26 +261,40 @@ static void cmd_measure_speed(struct any_frame* f)
|
||||
{
|
||||
start_motor();
|
||||
|
||||
index_irq = false;
|
||||
while (!index_irq)
|
||||
;
|
||||
index_irq = false;
|
||||
int start_clock = clock;
|
||||
int elapsed = 0;
|
||||
while (!index_irq)
|
||||
;
|
||||
int end_clock = clock;
|
||||
{
|
||||
elapsed = clock - start_clock;
|
||||
if (elapsed > 1000)
|
||||
{
|
||||
elapsed = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (elapsed != 0)
|
||||
{
|
||||
index_irq = false;
|
||||
start_clock = clock;
|
||||
while (!index_irq)
|
||||
elapsed = clock - start_clock;
|
||||
}
|
||||
|
||||
DECLARE_REPLY_FRAME(struct speed_frame, F_FRAME_MEASURE_SPEED_REPLY);
|
||||
r.period_ms = end_clock - start_clock;
|
||||
r.period_ms = elapsed;
|
||||
send_reply((struct any_frame*) &r);
|
||||
}
|
||||
|
||||
static void cmd_bulk_test(struct any_frame* f)
|
||||
static void cmd_bulk_write_test(struct any_frame* f)
|
||||
{
|
||||
uint8_t buffer[64];
|
||||
|
||||
wait_until_writeable(FLUXENGINE_DATA_IN_EP_NUM);
|
||||
for (int x=0; x<64; x++)
|
||||
{
|
||||
CyWdtClear();
|
||||
for (int y=0; y<256; y++)
|
||||
{
|
||||
for (unsigned z=0; z<sizeof(buffer); z++)
|
||||
@@ -236,11 +303,50 @@ static void cmd_bulk_test(struct any_frame* f)
|
||||
wait_until_writeable(FLUXENGINE_DATA_IN_EP_NUM);
|
||||
USBFS_LoadInEP(FLUXENGINE_DATA_IN_EP_NUM, buffer, sizeof(buffer));
|
||||
}
|
||||
}
|
||||
|
||||
DECLARE_REPLY_FRAME(struct any_frame, F_FRAME_BULK_TEST_REPLY);
|
||||
DECLARE_REPLY_FRAME(struct any_frame, F_FRAME_BULK_WRITE_TEST_REPLY);
|
||||
send_reply(&r);
|
||||
}
|
||||
|
||||
static void cmd_bulk_read_test(struct any_frame* f)
|
||||
{
|
||||
uint8_t buffer[64];
|
||||
|
||||
bool passed = true;
|
||||
for (int x=0; x<64; x++)
|
||||
{
|
||||
CyWdtClear();
|
||||
for (int y=0; y<256; y++)
|
||||
{
|
||||
USBFS_EnableOutEP(FLUXENGINE_DATA_OUT_EP_NUM);
|
||||
while (USBFS_GetEPState(FLUXENGINE_DATA_OUT_EP_NUM) != USBFS_OUT_BUFFER_FULL)
|
||||
;
|
||||
USBFS_ReadOutEP(FLUXENGINE_DATA_OUT_EP_NUM, buffer, sizeof(buffer));
|
||||
while (USBFS_GetEPState(FLUXENGINE_DATA_OUT_EP_NUM) != USBFS_OUT_BUFFER_EMPTY)
|
||||
;
|
||||
|
||||
for (unsigned z=0; z<sizeof(buffer); z++)
|
||||
{
|
||||
if (buffer[z] != (uint8)(x+y+z))
|
||||
{
|
||||
print("fail %d+%d+%d == %d, not %d", x, y, z, buffer[z], (uint8)(x+y+z));
|
||||
passed = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
print("passed=%d", passed);
|
||||
if (passed)
|
||||
{
|
||||
DECLARE_REPLY_FRAME(struct any_frame, F_FRAME_BULK_READ_TEST_REPLY);
|
||||
send_reply(&r);
|
||||
}
|
||||
else
|
||||
send_error(F_ERROR_INVALID_VALUE);
|
||||
}
|
||||
|
||||
static void deinit_dma(void)
|
||||
{
|
||||
for (int i=0; i<BUFFER_COUNT; i++)
|
||||
@@ -249,7 +355,7 @@ static void deinit_dma(void)
|
||||
|
||||
static void init_capture_dma(void)
|
||||
{
|
||||
dma_channel = CAPTURE_DMA_DmaInitialize(
|
||||
dma_channel = SAMPLER_DMA_DmaInitialize(
|
||||
2 /* bytes */,
|
||||
true /* request per burst */,
|
||||
HI16(CYDEV_PERIPH_BASE),
|
||||
@@ -264,8 +370,8 @@ static void init_capture_dma(void)
|
||||
nexti = 0;
|
||||
|
||||
CyDmaTdSetConfiguration(td[i], BUFFER_SIZE, td[nexti],
|
||||
CY_DMA_TD_INC_DST_ADR | CAPTURE_DMA__TD_TERMOUT_EN);
|
||||
CyDmaTdSetAddress(td[i], LO16((uint32)&SAMPLER_DATAPATH_F0_REG), LO16((uint32)&dma_buffer[i]));
|
||||
CY_DMA_TD_INC_DST_ADR | SAMPLER_DMA__TD_TERMOUT_EN);
|
||||
CyDmaTdSetAddress(td[i], LO16((uint32)SAMPLER_FIFO_FIFO_PTR), LO16((uint32)&dma_buffer[i]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -276,37 +382,35 @@ static void cmd_read(struct read_frame* f)
|
||||
|
||||
/* Do slow setup *before* we go into the real-time bit. */
|
||||
|
||||
SAMPLER_CONTROL_Write(1); /* reset */
|
||||
|
||||
{
|
||||
uint8_t i = CyEnterCriticalSection();
|
||||
SAMPLER_DATAPATH_F0_SET_LEVEL_MID;
|
||||
SAMPLER_DATAPATH_F0_CLEAR;
|
||||
SAMPLER_DATAPATH_F0_SINGLE_BUFFER_UNSET;
|
||||
SAMPLER_FIFO_SET_LEVEL_NORMAL;
|
||||
SAMPLER_FIFO_CLEAR;
|
||||
SAMPLER_FIFO_SINGLE_BUFFER_UNSET;
|
||||
CyExitCriticalSection(i);
|
||||
}
|
||||
|
||||
wait_until_writeable(FLUXENGINE_DATA_IN_EP_NUM);
|
||||
init_capture_dma();
|
||||
|
||||
/* Wait for the beginning of a rotation. */
|
||||
/* Wait for the beginning of a rotation, if requested. */
|
||||
|
||||
print("wait");
|
||||
index_irq = false;
|
||||
while (!index_irq)
|
||||
;
|
||||
index_irq = false;
|
||||
if (f->synced)
|
||||
{
|
||||
index_irq = false;
|
||||
while (!index_irq)
|
||||
;
|
||||
index_irq = false;
|
||||
}
|
||||
|
||||
crunch_state_t cs = {};
|
||||
cs.outputptr = usb_buffer;
|
||||
cs.outputptr = xfer_buffer;
|
||||
cs.outputlen = BUFFER_SIZE;
|
||||
|
||||
dma_writing_to_td = 0;
|
||||
dma_reading_from_td = -1;
|
||||
dma_underrun = false;
|
||||
int count = 0;
|
||||
SAMPLER_CONTROL_Write(0); /* !reset */
|
||||
CAPTURE_CONTROL_Write(1);
|
||||
CyDmaChSetInitialTd(dma_channel, td[dma_writing_to_td]);
|
||||
CyDmaClearPendingDrq(dma_channel);
|
||||
CyDmaChEnable(dma_channel, 1);
|
||||
@@ -314,74 +418,100 @@ static void cmd_read(struct read_frame* f)
|
||||
/* Wait for the first DMA transfer to complete, after which we can start the
|
||||
* USB transfer. */
|
||||
|
||||
while ((dma_writing_to_td == 0) && !index_irq)
|
||||
while (dma_writing_to_td == 0)
|
||||
;
|
||||
dma_reading_from_td = 0;
|
||||
bool dma_running = true;
|
||||
|
||||
/* Start transferring. */
|
||||
|
||||
int revolutions = f->revolutions;
|
||||
while (!dma_underrun)
|
||||
uint32_t start_time = clock;
|
||||
for (;;)
|
||||
{
|
||||
CyWdtClear();
|
||||
|
||||
/* Have we reached the index pulse? */
|
||||
if (index_irq)
|
||||
{
|
||||
index_irq = false;
|
||||
revolutions--;
|
||||
if (revolutions == 0)
|
||||
break;
|
||||
}
|
||||
/* If the sample session is over, stop reading but continue processing until
|
||||
* the DMA chain is empty. */
|
||||
|
||||
/* Wait for the next block to be read. */
|
||||
while (dma_reading_from_td == dma_writing_to_td)
|
||||
if ((clock - start_time) >= f->milliseconds)
|
||||
{
|
||||
/* On an underrun, give up immediately. */
|
||||
if (dma_underrun)
|
||||
goto abort;
|
||||
}
|
||||
|
||||
uint8_t dma_buffer_usage = 0;
|
||||
while (dma_buffer_usage < BUFFER_SIZE)
|
||||
{
|
||||
cs.inputptr = dma_buffer[dma_reading_from_td] + dma_buffer_usage;
|
||||
cs.inputlen = BUFFER_SIZE - dma_buffer_usage;
|
||||
crunch(&cs);
|
||||
dma_buffer_usage += BUFFER_SIZE - cs.inputlen;
|
||||
count++;
|
||||
if (cs.outputlen == 0)
|
||||
if (dma_running)
|
||||
{
|
||||
while (USBFS_GetEPState(FLUXENGINE_DATA_IN_EP_NUM) != USBFS_IN_BUFFER_EMPTY)
|
||||
{
|
||||
if (index_irq || dma_underrun)
|
||||
goto abort;
|
||||
}
|
||||
|
||||
USBFS_LoadInEP(FLUXENGINE_DATA_IN_EP_NUM, usb_buffer, BUFFER_SIZE);
|
||||
cs.outputptr = usb_buffer;
|
||||
cs.outputlen = BUFFER_SIZE;
|
||||
CyDmaChSetRequest(dma_channel, CY_DMA_CPU_TERM_CHAIN);
|
||||
while (CyDmaChGetRequest(dma_channel))
|
||||
;
|
||||
dma_running = false;
|
||||
dma_underrun = false;
|
||||
}
|
||||
}
|
||||
dma_reading_from_td = NEXT_BUFFER(dma_reading_from_td);
|
||||
|
||||
/* If there's an underrun event, stop immediately. */
|
||||
|
||||
if (dma_underrun)
|
||||
goto abort;
|
||||
|
||||
/* If there are no more blocks to be read, check to see if we've finished. */
|
||||
|
||||
if (dma_reading_from_td == dma_writing_to_td)
|
||||
{
|
||||
/* Also if we've run out of blocks to send. */
|
||||
|
||||
if (!dma_running)
|
||||
goto abort;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise, there's a block waiting, so attempt to send it. */
|
||||
|
||||
uint8_t dma_buffer_usage = 0;
|
||||
while (dma_buffer_usage < BUFFER_SIZE)
|
||||
{
|
||||
cs.inputptr = dma_buffer[dma_reading_from_td] + dma_buffer_usage;
|
||||
cs.inputlen = BUFFER_SIZE - dma_buffer_usage;
|
||||
crunch(&cs);
|
||||
dma_buffer_usage += BUFFER_SIZE - cs.inputlen;
|
||||
count++;
|
||||
|
||||
/* If there is no available space in the output buffer, flush the buffer via
|
||||
* USB and go again. */
|
||||
if (cs.outputlen == 0)
|
||||
{
|
||||
wait_until_writeable(FLUXENGINE_DATA_IN_EP_NUM);
|
||||
memcpy(usb_buffer, xfer_buffer, FRAME_SIZE);
|
||||
USBFS_LoadInEP(FLUXENGINE_DATA_IN_EP_NUM, usb_buffer, BUFFER_SIZE);
|
||||
|
||||
cs.outputptr = xfer_buffer;
|
||||
cs.outputlen = BUFFER_SIZE;
|
||||
}
|
||||
}
|
||||
dma_reading_from_td = NEXT_BUFFER(dma_reading_from_td);
|
||||
}
|
||||
}
|
||||
abort:;
|
||||
CAPTURE_CONTROL_Write(0);
|
||||
CyDmaChSetRequest(dma_channel, CY_DMA_CPU_TERM_CHAIN);
|
||||
while (CyDmaChGetRequest(dma_channel))
|
||||
;
|
||||
bool saved_dma_underrun = dma_underrun;
|
||||
|
||||
donecrunch(&cs);
|
||||
wait_until_writeable(FLUXENGINE_DATA_IN_EP_NUM);
|
||||
unsigned zz = cs.outputlen;
|
||||
/* If there's a complete packet waiting, send it. */
|
||||
if (cs.outputlen != BUFFER_SIZE)
|
||||
{
|
||||
USBFS_LoadInEP(FLUXENGINE_DATA_IN_EP_NUM, usb_buffer, BUFFER_SIZE);
|
||||
wait_until_writeable(FLUXENGINE_DATA_IN_EP_NUM);
|
||||
}
|
||||
if ((cs.outputlen != 0) && (cs.outputlen != BUFFER_SIZE))
|
||||
{
|
||||
/* If there's a partial packet waiting, send it; this will also terminate the transfer. */
|
||||
USBFS_LoadInEP(FLUXENGINE_DATA_IN_EP_NUM, usb_buffer, BUFFER_SIZE-cs.outputlen);
|
||||
if ((cs.outputlen == BUFFER_SIZE) || (cs.outputlen == 0))
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise just terminate the transfer. */
|
||||
USBFS_LoadInEP(FLUXENGINE_DATA_IN_EP_NUM, NULL, 0);
|
||||
}
|
||||
wait_until_writeable(FLUXENGINE_DATA_IN_EP_NUM);
|
||||
deinit_dma();
|
||||
|
||||
if (dma_underrun)
|
||||
if (saved_dma_underrun)
|
||||
{
|
||||
print("underrun after %d packets");
|
||||
send_error(F_ERROR_UNDERRUN);
|
||||
@@ -391,7 +521,7 @@ abort:;
|
||||
DECLARE_REPLY_FRAME(struct any_frame, F_FRAME_READ_REPLY);
|
||||
send_reply(&r);
|
||||
}
|
||||
print("count=%d i=%d d=%d zz=%d", count, index_irq, dma_underrun, zz);
|
||||
print("count=%d i=%d d=%d", count, index_irq, dma_underrun);
|
||||
}
|
||||
|
||||
static void init_replay_dma(void)
|
||||
@@ -412,25 +542,28 @@ static void init_replay_dma(void)
|
||||
|
||||
CyDmaTdSetConfiguration(td[i], BUFFER_SIZE, td[nexti],
|
||||
CY_DMA_TD_INC_SRC_ADR | SEQUENCER_DMA__TD_TERMOUT_EN);
|
||||
CyDmaTdSetAddress(td[i], LO16((uint32)&dma_buffer[i]), LO16((uint32)&SEQUENCER_DATAPATH_F0_REG));
|
||||
CyDmaTdSetAddress(td[i], LO16((uint32)&dma_buffer[i]), LO16((uint32)REPLAY_FIFO_FIFO_PTR));
|
||||
}
|
||||
}
|
||||
|
||||
static void cmd_write(struct write_frame* f)
|
||||
{
|
||||
print("cmd_write");
|
||||
|
||||
if (f->bytes_to_write % FRAME_SIZE)
|
||||
{
|
||||
send_error(F_ERROR_INVALID_VALUE);
|
||||
return;
|
||||
}
|
||||
|
||||
SEQUENCER_CONTROL_Write(1); /* put the sequencer into reset */
|
||||
|
||||
SIDE_REG_Write(f->side);
|
||||
SEQUENCER_CONTROL_Write(1); /* reset */
|
||||
{
|
||||
uint8_t i = CyEnterCriticalSection();
|
||||
SEQUENCER_DATAPATH_F0_SET_LEVEL_NORMAL;
|
||||
SEQUENCER_DATAPATH_F0_CLEAR;
|
||||
SEQUENCER_DATAPATH_F0_SINGLE_BUFFER_UNSET;
|
||||
uint8_t i = CyEnterCriticalSection();
|
||||
REPLAY_FIFO_SET_LEVEL_MID;
|
||||
REPLAY_FIFO_CLEAR;
|
||||
REPLAY_FIFO_SINGLE_BUFFER_UNSET;
|
||||
CyExitCriticalSection(i);
|
||||
}
|
||||
seek_to(current_track);
|
||||
@@ -441,6 +574,7 @@ static void cmd_write(struct write_frame* f)
|
||||
int packets = f->bytes_to_write / FRAME_SIZE;
|
||||
int count_written = 0;
|
||||
int count_read = 0;
|
||||
int packetwaiting = 0;
|
||||
dma_writing_to_td = 0;
|
||||
dma_reading_from_td = -1;
|
||||
dma_underrun = false;
|
||||
@@ -452,6 +586,22 @@ static void cmd_write(struct write_frame* f)
|
||||
int old_reading_from_td = -1;
|
||||
for (;;)
|
||||
{
|
||||
CyWdtClear();
|
||||
|
||||
/* Make sure that we always have a USB read in progress whenever possible. */
|
||||
|
||||
if (!finished && !packetwaiting)
|
||||
{
|
||||
/* There is no read in progress; has data arrived in the external USB buffer? */
|
||||
|
||||
if (USBFS_GetEPState(FLUXENGINE_DATA_OUT_EP_NUM) == USBFS_OUT_BUFFER_FULL)
|
||||
{
|
||||
/* Yes, data has arrived, so initiate the copy. */
|
||||
|
||||
packetwaiting = USBFS_ReadOutEP(FLUXENGINE_DATA_OUT_EP_NUM, usb_buffer, FRAME_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Read data from USB into the buffers. */
|
||||
|
||||
if (NEXT_BUFFER(dma_writing_to_td) != dma_reading_from_td)
|
||||
@@ -468,26 +618,33 @@ static void cmd_write(struct write_frame* f)
|
||||
/* There's no more data to read, so fake some. */
|
||||
|
||||
for (int i=0; i<BUFFER_SIZE; i++)
|
||||
usb_buffer[i+0] = 0x7f;
|
||||
cs.inputptr = usb_buffer;
|
||||
xfer_buffer[i+0] = 0x7f;
|
||||
cs.inputptr = xfer_buffer;
|
||||
cs.inputlen = BUFFER_SIZE;
|
||||
}
|
||||
else
|
||||
else if (packetwaiting)
|
||||
{
|
||||
while (USBFS_GetEPState(FLUXENGINE_DATA_OUT_EP_NUM) != USBFS_OUT_BUFFER_FULL)
|
||||
/* There's a USB read into usb_buffer in progress, so check if it's finished. */
|
||||
|
||||
if (USBFS_GetEPState(FLUXENGINE_DATA_OUT_EP_NUM) == USBFS_OUT_BUFFER_EMPTY)
|
||||
{
|
||||
if (writing && (dma_underrun || index_irq))
|
||||
goto abort;
|
||||
/* It's done, so copy out the data. */
|
||||
|
||||
memcpy(xfer_buffer, usb_buffer, FRAME_SIZE);
|
||||
cs.inputptr = xfer_buffer;
|
||||
cs.inputlen = packetwaiting;
|
||||
|
||||
count_read++;
|
||||
if ((packetwaiting < FRAME_SIZE) || (count_read == packets))
|
||||
finished = true;
|
||||
else
|
||||
{
|
||||
/* Wait for more USB data to show up. */
|
||||
|
||||
packetwaiting = 0;
|
||||
USBFS_EnableOutEP(FLUXENGINE_DATA_OUT_EP_NUM);
|
||||
}
|
||||
}
|
||||
|
||||
int length = usb_read(FLUXENGINE_DATA_OUT_EP_NUM, usb_buffer);
|
||||
cs.inputptr = usb_buffer;
|
||||
cs.inputlen = length;
|
||||
USBFS_EnableOutEP(FLUXENGINE_DATA_OUT_EP_NUM);
|
||||
|
||||
count_read++;
|
||||
if ((length < FRAME_SIZE) || (count_read == packets))
|
||||
finished = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -506,7 +663,8 @@ static void cmd_write(struct write_frame* f)
|
||||
}
|
||||
}
|
||||
|
||||
/* If we have a full buffer, start writing. */
|
||||
/* Once all the buffers are full, start writing. */
|
||||
|
||||
if ((dma_reading_from_td == -1) && (dma_writing_to_td == BUFFER_COUNT-1))
|
||||
{
|
||||
dma_reading_from_td = old_reading_from_td = 0;
|
||||
@@ -521,7 +679,7 @@ static void cmd_write(struct write_frame* f)
|
||||
|
||||
/* Wait for the index marker. While this happens, the DMA engine
|
||||
* will prime the FIFO. */
|
||||
|
||||
|
||||
index_irq = false;
|
||||
while (!index_irq)
|
||||
;
|
||||
@@ -532,7 +690,7 @@ static void cmd_write(struct write_frame* f)
|
||||
SEQUENCER_CONTROL_Write(0); /* start writing! */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (writing && (dma_underrun || index_irq))
|
||||
goto abort;
|
||||
|
||||
@@ -543,6 +701,7 @@ static void cmd_write(struct write_frame* f)
|
||||
}
|
||||
}
|
||||
abort:
|
||||
print("done %d %d", dma_reading_from_td, dma_writing_to_td);
|
||||
SEQUENCER_DMA_FINISHED_IRQ_Disable();
|
||||
|
||||
SEQUENCER_CONTROL_Write(1); /* reset */
|
||||
@@ -555,10 +714,12 @@ abort:
|
||||
CyDmaChDisable(dma_channel);
|
||||
}
|
||||
|
||||
//debug("p=%d cr=%d cw=%d f=%d l=%d w=%d index=%d underrun=%d", packets, count_read, count_written, finished, listening, writing, index_irq, dma_underrun);
|
||||
print("p=%d cr=%d cw=%d f=%d w=%d index=%d underrun=%d", packets, count_read, count_written, finished, writing, index_irq, dma_underrun);
|
||||
if (!finished)
|
||||
{
|
||||
while (count_read < packets)
|
||||
/* There's still some data to read, so just read and blackhole it ---
|
||||
* easier than trying to terminate the connection. */
|
||||
while (count_read != packets)
|
||||
{
|
||||
if (USBFS_GetEPState(FLUXENGINE_DATA_OUT_EP_NUM) == USBFS_OUT_BUFFER_FULL)
|
||||
{
|
||||
@@ -573,6 +734,7 @@ abort:
|
||||
}
|
||||
|
||||
deinit_dma();
|
||||
print("write finished");
|
||||
|
||||
if (dma_underrun)
|
||||
{
|
||||
@@ -607,17 +769,105 @@ static void cmd_erase(struct erase_frame* f)
|
||||
|
||||
static void cmd_set_drive(struct set_drive_frame* f)
|
||||
{
|
||||
if (current_drive_flags != f->drive_flags)
|
||||
{
|
||||
current_drive_flags = f->drive_flags;
|
||||
DRIVE_REG_Write(current_drive_flags);
|
||||
homed = false;
|
||||
}
|
||||
if (drive0_present && !drive1_present)
|
||||
f->drive = 0;
|
||||
if (drive1_present && !drive0_present)
|
||||
f->drive = 1;
|
||||
set_drive_flags(f);
|
||||
|
||||
DECLARE_REPLY_FRAME(struct any_frame, F_FRAME_SET_DRIVE_REPLY);
|
||||
send_reply((struct any_frame*) &r);
|
||||
}
|
||||
|
||||
|
||||
static uint16_t read_output_voltage_mv(void)
|
||||
{
|
||||
OUTPUT_VOLTAGE_ADC_StartConvert();
|
||||
OUTPUT_VOLTAGE_ADC_IsEndConversion(OUTPUT_VOLTAGE_ADC_WAIT_FOR_RESULT);
|
||||
uint16_t samples = OUTPUT_VOLTAGE_ADC_GetResult16();
|
||||
return OUTPUT_VOLTAGE_ADC_CountsTo_mVolts(samples);
|
||||
}
|
||||
|
||||
static void read_output_voltages(struct voltages* v)
|
||||
{
|
||||
SIDE_REG_Write(1); /* set DIR to low (remember this is inverted) */
|
||||
CyDelay(100);
|
||||
v->logic0_mv = read_output_voltage_mv();
|
||||
|
||||
SIDE_REG_Write(0);
|
||||
CyDelay(100);
|
||||
v->logic1_mv = read_output_voltage_mv();
|
||||
}
|
||||
|
||||
static uint16_t read_input_voltage_mv(void)
|
||||
{
|
||||
INPUT_VOLTAGE_ADC_StartConvert();
|
||||
INPUT_VOLTAGE_ADC_IsEndConversion(INPUT_VOLTAGE_ADC_WAIT_FOR_RESULT);
|
||||
uint16_t samples = INPUT_VOLTAGE_ADC_GetResult16();
|
||||
return INPUT_VOLTAGE_ADC_CountsTo_mVolts(samples);
|
||||
}
|
||||
|
||||
static void read_input_voltages(struct voltages* v)
|
||||
{
|
||||
home();
|
||||
CyDelay(50);
|
||||
v->logic0_mv = read_input_voltage_mv();
|
||||
|
||||
step(STEP_AWAYFROM0);
|
||||
CyDelay(50);
|
||||
v->logic1_mv = read_input_voltage_mv();
|
||||
}
|
||||
|
||||
static void cmd_measure_voltages(void)
|
||||
{
|
||||
stop_motor();
|
||||
INPUT_VOLTAGE_ADC_Start();
|
||||
INPUT_VOLTAGE_ADC_SetPower(INPUT_VOLTAGE_ADC__HIGHPOWER);
|
||||
OUTPUT_VOLTAGE_ADC_Start();
|
||||
OUTPUT_VOLTAGE_ADC_SetPower(OUTPUT_VOLTAGE_ADC__HIGHPOWER);
|
||||
|
||||
DECLARE_REPLY_FRAME(struct voltages_frame, F_FRAME_MEASURE_VOLTAGES_REPLY);
|
||||
|
||||
CyWdtClear();
|
||||
MOTOR_REG_Write(0); /* should be ignored anyway */
|
||||
DRIVESELECT_REG_Write(0); /* deselect both drives */
|
||||
CyDelay(200); /* wait for things to settle */
|
||||
read_output_voltages(&r.output_both_off);
|
||||
read_input_voltages(&r.input_both_off);
|
||||
|
||||
CyWdtClear();
|
||||
DRIVESELECT_REG_Write(1); /* select drive 0 */
|
||||
CyDelay(50);
|
||||
read_output_voltages(&r.output_drive_0_selected);
|
||||
read_input_voltages(&r.input_drive_0_selected);
|
||||
MOTOR_REG_Write(1);
|
||||
CyDelay(300);
|
||||
CyWdtClear();
|
||||
read_output_voltages(&r.output_drive_0_running);
|
||||
read_input_voltages(&r.input_drive_0_running);
|
||||
MOTOR_REG_Write(0);
|
||||
CyDelay(300);
|
||||
|
||||
CyWdtClear();
|
||||
DRIVESELECT_REG_Write(2); /* select drive 1 */
|
||||
CyDelay(50);
|
||||
read_output_voltages(&r.output_drive_1_selected);
|
||||
read_input_voltages(&r.input_drive_1_selected);
|
||||
MOTOR_REG_Write(1);
|
||||
CyDelay(300);
|
||||
CyWdtClear();
|
||||
read_output_voltages(&r.output_drive_1_running);
|
||||
read_input_voltages(&r.input_drive_1_running);
|
||||
MOTOR_REG_Write(0);
|
||||
CyDelay(300);
|
||||
|
||||
CyWdtClear();
|
||||
DRIVESELECT_REG_Write(0);
|
||||
homed = false;
|
||||
INPUT_VOLTAGE_ADC_Stop();
|
||||
OUTPUT_VOLTAGE_ADC_Stop();
|
||||
send_reply((struct any_frame*) &r);
|
||||
}
|
||||
|
||||
static void handle_command(void)
|
||||
{
|
||||
static uint8_t input_buffer[FRAME_SIZE];
|
||||
@@ -639,8 +889,12 @@ static void handle_command(void)
|
||||
cmd_measure_speed(f);
|
||||
break;
|
||||
|
||||
case F_FRAME_BULK_TEST_CMD:
|
||||
cmd_bulk_test(f);
|
||||
case F_FRAME_BULK_WRITE_TEST_CMD:
|
||||
cmd_bulk_write_test(f);
|
||||
break;
|
||||
|
||||
case F_FRAME_BULK_READ_TEST_CMD:
|
||||
cmd_bulk_read_test(f);
|
||||
break;
|
||||
|
||||
case F_FRAME_READ_CMD:
|
||||
@@ -662,6 +916,10 @@ static void handle_command(void)
|
||||
case F_FRAME_SET_DRIVE_CMD:
|
||||
cmd_set_drive((struct set_drive_frame*) f);
|
||||
break;
|
||||
|
||||
case F_FRAME_MEASURE_VOLTAGES_CMD:
|
||||
cmd_measure_voltages();
|
||||
break;
|
||||
|
||||
default:
|
||||
send_error(F_ERROR_BAD_COMMAND);
|
||||
@@ -674,14 +932,28 @@ int main(void)
|
||||
CySysTickStart();
|
||||
CySysTickSetCallback(4, system_timer_cb);
|
||||
INDEX_IRQ_StartEx(&index_irq_cb);
|
||||
CAPTURE_DMA_FINISHED_IRQ_StartEx(&capture_dma_finished_irq_cb);
|
||||
SAMPLER_DMA_FINISHED_IRQ_StartEx(&capture_dma_finished_irq_cb);
|
||||
SEQUENCER_DMA_FINISHED_IRQ_StartEx(&replay_dma_finished_irq_cb);
|
||||
DRIVE_REG_Write(0);
|
||||
INPUT_VOLTAGE_ADC_Stop();
|
||||
OUTPUT_VOLTAGE_ADC_Stop();
|
||||
DRIVESELECT_REG_Write(0);
|
||||
UART_Start();
|
||||
USBFS_Start(0, USBFS_DWR_VDDD_OPERATION);
|
||||
|
||||
CyWdtStart(CYWDT_1024_TICKS, CYWDT_LPMODE_DISABLED);
|
||||
|
||||
current_drive_flags.drive = 0;
|
||||
start_motor();
|
||||
drive0_present = home();
|
||||
stop_motor();
|
||||
|
||||
current_drive_flags.drive = 1;
|
||||
start_motor();
|
||||
drive1_present = home();
|
||||
stop_motor();
|
||||
|
||||
print("drive 0: %s drive 1: %s", drive0_present ? "yes" : "no", drive1_present ? "yes" : "no");
|
||||
|
||||
/* UART_PutString("GO\r"); */
|
||||
|
||||
for (;;)
|
||||
@@ -692,10 +964,7 @@ int main(void)
|
||||
{
|
||||
uint32_t time_on = clock - motor_on_time;
|
||||
if (time_on > MOTOR_ON_TIME)
|
||||
{
|
||||
MOTOR_REG_Write(0);
|
||||
motor_on = false;
|
||||
}
|
||||
stop_motor();
|
||||
}
|
||||
|
||||
if (!USBFS_GetConfiguration() || USBFS_IsConfigurationChanged())
|
||||
@@ -709,6 +978,7 @@ int main(void)
|
||||
|
||||
if (USBFS_GetEPState(FLUXENGINE_CMD_OUT_EP_NUM) == USBFS_OUT_BUFFER_FULL)
|
||||
{
|
||||
set_drive_flags(¤t_drive_flags);
|
||||
handle_command();
|
||||
USBFS_EnableOutEP(FLUXENGINE_CMD_OUT_EP_NUM);
|
||||
print("idle");
|
||||
|
||||
18
Makefile
18
Makefile
@@ -1,8 +1,13 @@
|
||||
PACKAGES = zlib sqlite3 libusb-1.0
|
||||
|
||||
export CFLAGS = -Os -g --std=c++14 \
|
||||
-ffunction-sections -fdata-sections
|
||||
export LDFLAGS = -Os
|
||||
export CFLAGS = --std=c++14 -ffunction-sections -fdata-sections
|
||||
export LDFLAGS =
|
||||
|
||||
export COPTFLAGS = -Os
|
||||
export LDOPTFLAGS = -Os -s
|
||||
|
||||
export CDBGFLAGS = -O0 -g
|
||||
export LDDBGFLAGS = -O0 -g
|
||||
|
||||
ifeq ($(OS), Windows_NT)
|
||||
export CXX = /mingw32/bin/g++
|
||||
@@ -13,6 +18,13 @@ export LDFLAGS +=
|
||||
export LIBS = -static -lz -lsqlite3 -lusb-1.0
|
||||
export EXTENSION = .exe
|
||||
else
|
||||
|
||||
packages-exist = $(shell pkg-config --exists $(PACKAGES) && echo yes)
|
||||
ifneq ($(packages-exist),yes)
|
||||
$(warning These pkg-config packages are installed: $(shell pkg-config --list-all | sort | awk '{print $$1}'))
|
||||
$(error You must have these pkg-config packages installed: $(PACKAGES))
|
||||
endif
|
||||
|
||||
export CXX = g++
|
||||
export AR = ar rcs
|
||||
export STRIP = strip
|
||||
|
||||
16
README.md
16
README.md
@@ -79,20 +79,24 @@ people who've had it work).
|
||||
|
||||
| Format | Read? | Write? | Notes |
|
||||
|:-----------------------------------------|:-----:|:------:|-------|
|
||||
| IBM PC compatible | 🦄 | | and compatibles (like the Atari ST) |
|
||||
| [Acorn ADFS](doc/disk-acornadfs.md) | 🦄 | | single- and double- sided |
|
||||
| [Acorn DFS](doc/disk-acorndfs.md) | 🦄 | | |
|
||||
| [Ampro Little Board](doc/disk-ampro.md) | 🦖 | | |
|
||||
| [IBM PC compatible](doc/disk-ibm.md) | 🦄 | 🦄 | and compatibles (like the Atari ST) |
|
||||
| [Acorn ADFS](doc/disk-acornadfs.md) | 🦄 | 🦖* | single- and double- sided |
|
||||
| [Acorn DFS](doc/disk-acorndfs.md) | 🦄 | 🦖* | |
|
||||
| [Ampro Little Board](doc/disk-ampro.md) | 🦖 | 🦖* | |
|
||||
| [Apple II DOS 3.3](doc/disk-apple2.md) | 🦄 | | doesn't do logical sector remapping |
|
||||
| [Amiga](doc/disk-amiga.md) | 🦄 | | |
|
||||
| [Commodore 64 1541](doc/disk-c64.md) | 🦖 | | and probably the other GCR formats |
|
||||
| [Brother 120kB](doc/disk-brother.md) | 🦄 | | |
|
||||
| [Brother 240kB](doc/disk-brother.md) | 🦄 | 🦄 | |
|
||||
| [Brother FB-100](doc/disk-fb100.md) | 🦖 | | Tandy Model 100, Husky Hunter, knitting machines |
|
||||
| [Macintosh 800kB](doc/disk-macintosh.md) | 🦄 | | and probably the 400kB too |
|
||||
| [TRS-80](doc/disk-trs80.md) | 🦖 | | a minor variation of the IBM scheme |
|
||||
| [Macintosh 800kB](doc/disk-macintosh.md) | 🦖 | | and probably the 400kB too |
|
||||
| [TRS-80](doc/disk-trs80.md) | 🦖 | 🦖* | a minor variation of the IBM scheme |
|
||||
{: .datatable }
|
||||
|
||||
`*`: these formats are variations of the generic IBM format, and since the
|
||||
IBM writer is completely generic, it should be configurable for these
|
||||
formats... theoretically. I don't have the hardware to try it.
|
||||
|
||||
### Even older disk formats
|
||||
|
||||
These formats are for particularly old, weird architectures, even by the
|
||||
|
||||
101
arch/amiga/amiga.cc
Normal file
101
arch/amiga/amiga.cc
Normal file
@@ -0,0 +1,101 @@
|
||||
#include "globals.h"
|
||||
#include "record.h"
|
||||
#include "decoders/decoders.h"
|
||||
#include "amiga.h"
|
||||
#include "bytes.h"
|
||||
#include "fmt/format.h"
|
||||
|
||||
uint32_t amigaChecksum(const Bytes& bytes)
|
||||
{
|
||||
ByteReader br(bytes);
|
||||
uint32_t checksum = 0;
|
||||
|
||||
assert((bytes.size() & 3) == 0);
|
||||
while (!br.eof())
|
||||
checksum ^= br.read_be32();
|
||||
|
||||
return checksum & 0x55555555;
|
||||
}
|
||||
|
||||
static uint8_t everyother(uint16_t x)
|
||||
{
|
||||
/* aabb ccdd eeff gghh */
|
||||
x &= 0x6666; /* 0ab0 0cd0 0ef0 0gh0 */
|
||||
x >>= 1; /* 00ab 00cd 00ef 00gh */
|
||||
x |= x << 2; /* abab cdcd efef ghgh */
|
||||
x &= 0x3c3c; /* 00ab cd00 00ef gh00 */
|
||||
x >>= 2; /* 0000 abcd 0000 efgh */
|
||||
x |= x >> 4; /* 0000 abcd abcd efgh */
|
||||
return x;
|
||||
}
|
||||
|
||||
Bytes amigaInterleave(const Bytes& input)
|
||||
{
|
||||
Bytes output;
|
||||
ByteWriter bw(output);
|
||||
|
||||
/* Write all odd bits. (Numbering starts at 0...) */
|
||||
|
||||
{
|
||||
ByteReader br(input);
|
||||
while (!br.eof())
|
||||
{
|
||||
uint16_t x = br.read_be16();
|
||||
x &= 0xaaaa; /* a0b0 c0d0 e0f0 g0h0 */
|
||||
x |= x >> 1; /* aabb ccdd eeff gghh */
|
||||
x = everyother(x); /* 0000 0000 abcd efgh */
|
||||
bw.write_8(x);
|
||||
}
|
||||
}
|
||||
|
||||
/* Write all even bits. */
|
||||
|
||||
{
|
||||
ByteReader br(input);
|
||||
while (!br.eof())
|
||||
{
|
||||
uint16_t x = br.read_be16();
|
||||
x &= 0x5555; /* 0a0b 0c0d 0e0f 0g0h */
|
||||
x |= x << 1; /* aabb ccdd eeff gghh */
|
||||
x = everyother(x); /* 0000 0000 abcd efgh */
|
||||
bw.write_8(x);
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
Bytes amigaDeinterleave(const uint8_t*& input, size_t len)
|
||||
{
|
||||
assert(!(len & 1));
|
||||
const uint8_t* odds = &input[0];
|
||||
const uint8_t* evens = &input[len/2];
|
||||
Bytes output;
|
||||
ByteWriter bw(output);
|
||||
|
||||
for (size_t i=0; i<len/2; i++)
|
||||
{
|
||||
uint8_t o = *odds++;
|
||||
uint8_t e = *evens++;
|
||||
|
||||
/* This is the 'Interleave bits with 64-bit multiply' technique from
|
||||
* http://graphics.stanford.edu/~seander/bithacks.html#InterleaveBMN
|
||||
*/
|
||||
uint16_t result =
|
||||
(((e * 0x0101010101010101ULL & 0x8040201008040201ULL)
|
||||
* 0x0102040810204081ULL >> 49) & 0x5555) |
|
||||
(((o * 0x0101010101010101ULL & 0x8040201008040201ULL)
|
||||
* 0x0102040810204081ULL >> 48) & 0xAAAA);
|
||||
|
||||
bw.write_be16(result);
|
||||
}
|
||||
|
||||
input += len;
|
||||
return output;
|
||||
}
|
||||
|
||||
Bytes amigaDeinterleave(const Bytes& input)
|
||||
{
|
||||
const uint8_t* ptr = input.cbegin();
|
||||
return amigaDeinterleave(ptr, input.size());
|
||||
}
|
||||
@@ -1,12 +1,17 @@
|
||||
#ifndef AMIGA_H
|
||||
#define AMIGA_H
|
||||
|
||||
#include "encoders/encoders.h"
|
||||
|
||||
#define AMIGA_SECTOR_RECORD 0xaaaa44894489LL
|
||||
|
||||
#define AMIGA_TRACKS_PER_DISK 80
|
||||
#define AMIGA_SECTORS_PER_TRACK 11
|
||||
#define AMIGA_RECORD_SIZE 0x21f
|
||||
|
||||
class Sector;
|
||||
class Fluxmap;
|
||||
class SectorSet;
|
||||
|
||||
class AmigaDecoder : public AbstractDecoder
|
||||
{
|
||||
@@ -17,4 +22,20 @@ public:
|
||||
void decodeSectorRecord();
|
||||
};
|
||||
|
||||
class AmigaEncoder : public AbstractEncoder
|
||||
{
|
||||
public:
|
||||
virtual ~AmigaEncoder() {}
|
||||
|
||||
public:
|
||||
std::unique_ptr<Fluxmap> encode(int physicalTrack, int physicalSide, const SectorSet& allSectors);
|
||||
};
|
||||
|
||||
extern FlagGroup amigaEncoderFlags;
|
||||
|
||||
extern uint32_t amigaChecksum(const Bytes& bytes);
|
||||
extern Bytes amigaInterleave(const Bytes& input);
|
||||
extern Bytes amigaDeinterleave(const uint8_t*& input, size_t len);
|
||||
extern Bytes amigaDeinterleave(const Bytes& input);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -21,47 +21,6 @@
|
||||
|
||||
static const FluxPattern SECTOR_PATTERN(48, AMIGA_SECTOR_RECORD);
|
||||
|
||||
static Bytes deinterleave(const uint8_t*& input, size_t len)
|
||||
{
|
||||
assert(!(len & 1));
|
||||
const uint8_t* odds = &input[0];
|
||||
const uint8_t* evens = &input[len/2];
|
||||
Bytes output;
|
||||
ByteWriter bw(output);
|
||||
|
||||
for (size_t i=0; i<len/2; i++)
|
||||
{
|
||||
uint8_t o = *odds++;
|
||||
uint8_t e = *evens++;
|
||||
|
||||
/* This is the 'Interleave bits with 64-bit multiply' technique from
|
||||
* http://graphics.stanford.edu/~seander/bithacks.html#InterleaveBMN
|
||||
*/
|
||||
uint16_t result =
|
||||
(((e * 0x0101010101010101ULL & 0x8040201008040201ULL)
|
||||
* 0x0102040810204081ULL >> 49) & 0x5555) |
|
||||
(((o * 0x0101010101010101ULL & 0x8040201008040201ULL)
|
||||
* 0x0102040810204081ULL >> 48) & 0xAAAA);
|
||||
|
||||
bw.write_be16(result);
|
||||
}
|
||||
|
||||
input += len;
|
||||
return output;
|
||||
}
|
||||
|
||||
static uint32_t checksum(const Bytes& bytes)
|
||||
{
|
||||
ByteReader br(bytes);
|
||||
uint32_t checksum = 0;
|
||||
|
||||
assert((bytes.size() & 3) == 0);
|
||||
while (!br.eof())
|
||||
checksum ^= br.read_be32();
|
||||
|
||||
return checksum & 0x55555555;
|
||||
}
|
||||
|
||||
AbstractDecoder::RecordType AmigaDecoder::advanceToNextRecord()
|
||||
{
|
||||
_sector->clock = _fmr->seekToPattern(SECTOR_PATTERN);
|
||||
@@ -78,22 +37,22 @@ void AmigaDecoder::decodeSectorRecord()
|
||||
|
||||
const uint8_t* ptr = bytes.begin() + 3;
|
||||
|
||||
Bytes header = deinterleave(ptr, 4);
|
||||
Bytes recoveryinfo = deinterleave(ptr, 16);
|
||||
Bytes header = amigaDeinterleave(ptr, 4);
|
||||
Bytes recoveryinfo = amigaDeinterleave(ptr, 16);
|
||||
|
||||
_sector->logicalTrack = header[1] >> 1;
|
||||
_sector->logicalSide = header[1] & 1;
|
||||
_sector->logicalSector = header[2];
|
||||
|
||||
uint32_t wantedheaderchecksum = deinterleave(ptr, 4).reader().read_be32();
|
||||
uint32_t gotheaderchecksum = checksum(rawbytes.slice(6, 40));
|
||||
uint32_t wantedheaderchecksum = amigaDeinterleave(ptr, 4).reader().read_be32();
|
||||
uint32_t gotheaderchecksum = amigaChecksum(rawbytes.slice(6, 40));
|
||||
if (gotheaderchecksum != wantedheaderchecksum)
|
||||
return;
|
||||
|
||||
uint32_t wanteddatachecksum = deinterleave(ptr, 4).reader().read_be32();
|
||||
uint32_t gotdatachecksum = checksum(rawbytes.slice(62, 1024));
|
||||
uint32_t wanteddatachecksum = amigaDeinterleave(ptr, 4).reader().read_be32();
|
||||
uint32_t gotdatachecksum = amigaChecksum(rawbytes.slice(62, 1024));
|
||||
|
||||
_sector->data.clear();
|
||||
_sector->data.writer().append(deinterleave(ptr, 512)).append(recoveryinfo);
|
||||
_sector->data.writer().append(amigaDeinterleave(ptr, 512)).append(recoveryinfo);
|
||||
_sector->status = (gotdatachecksum == wanteddatachecksum) ? Sector::OK : Sector::BAD_CHECKSUM;
|
||||
}
|
||||
|
||||
129
arch/amiga/encoder.cc
Normal file
129
arch/amiga/encoder.cc
Normal file
@@ -0,0 +1,129 @@
|
||||
#include "globals.h"
|
||||
#include "record.h"
|
||||
#include "decoders/decoders.h"
|
||||
#include "encoders/encoders.h"
|
||||
#include "amiga.h"
|
||||
#include "crc.h"
|
||||
#include "sectorset.h"
|
||||
#include "writer.h"
|
||||
|
||||
FlagGroup amigaEncoderFlags;
|
||||
|
||||
static DoubleFlag clockRateUs(
|
||||
{ "--clock-rate" },
|
||||
"Encoded data clock rate (microseconds).",
|
||||
2.00);
|
||||
|
||||
static DoubleFlag postIndexGapMs(
|
||||
{ "--post-index-gap" },
|
||||
"Post-index gap before first sector header (milliseconds).",
|
||||
0.5);
|
||||
|
||||
static bool lastBit;
|
||||
|
||||
static int charToInt(char c)
|
||||
{
|
||||
if (isdigit(c))
|
||||
return c - '0';
|
||||
return 10 + tolower(c) - 'a';
|
||||
}
|
||||
|
||||
static void write_bits(std::vector<bool>& bits, unsigned& cursor, const std::vector<bool>& src)
|
||||
{
|
||||
for (bool bit : src)
|
||||
{
|
||||
if (cursor < bits.size())
|
||||
bits[cursor++] = bit;
|
||||
}
|
||||
}
|
||||
|
||||
static void write_bits(std::vector<bool>& bits, unsigned& cursor, uint64_t data, int width)
|
||||
{
|
||||
cursor += width;
|
||||
for (int i=0; i<width; i++)
|
||||
{
|
||||
unsigned pos = cursor - i - 1;
|
||||
if (pos < bits.size())
|
||||
bits[pos] = data & 1;
|
||||
data >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void write_interleaved_bytes(std::vector<bool>& bits, unsigned& cursor, const Bytes& bytes)
|
||||
{
|
||||
assert(!(bytes.size() & 3));
|
||||
Bytes interleaved = amigaInterleave(bytes);
|
||||
encodeMfm(bits, cursor, interleaved, lastBit);
|
||||
}
|
||||
|
||||
static void write_interleaved_bytes(std::vector<bool>& bits, unsigned& cursor, uint32_t data)
|
||||
{
|
||||
Bytes b(4);
|
||||
ByteWriter bw(b);
|
||||
bw.write_be32(data);
|
||||
write_interleaved_bytes(bits, cursor, b);
|
||||
}
|
||||
|
||||
static void write_sector(std::vector<bool>& bits, unsigned& cursor, const Sector* sector)
|
||||
{
|
||||
if ((sector->data.size() != 512) && (sector->data.size() != 528))
|
||||
Error() << "unsupported sector size --- you must pick 512 or 528";
|
||||
|
||||
write_bits(bits, cursor, AMIGA_SECTOR_RECORD, 6*8);
|
||||
|
||||
std::vector<bool> headerBits(20*16);
|
||||
unsigned headerCursor = 0;
|
||||
|
||||
Bytes header =
|
||||
{
|
||||
0xff, /* Amiga 1.0 format byte */
|
||||
(uint8_t) ((sector->logicalTrack<<1) | sector->logicalSide),
|
||||
(uint8_t) sector->logicalSector,
|
||||
(uint8_t) (AMIGA_SECTORS_PER_TRACK - sector->logicalSector)
|
||||
};
|
||||
write_interleaved_bytes(headerBits, headerCursor, header);
|
||||
Bytes recoveryInfo(16);
|
||||
if (sector->data.size() == 528)
|
||||
recoveryInfo = sector->data.slice(512, 16);
|
||||
write_interleaved_bytes(headerBits, headerCursor, recoveryInfo);
|
||||
|
||||
std::vector<bool> dataBits(512*16);
|
||||
unsigned dataCursor = 0;
|
||||
write_interleaved_bytes(dataBits, dataCursor, sector->data);
|
||||
|
||||
write_bits(bits, cursor, headerBits);
|
||||
uint32_t headerChecksum = amigaChecksum(toBytes(headerBits));
|
||||
write_interleaved_bytes(bits, cursor, headerChecksum);
|
||||
uint32_t dataChecksum = amigaChecksum(toBytes(dataBits));
|
||||
write_interleaved_bytes(bits, cursor, dataChecksum);
|
||||
write_bits(bits, cursor, dataBits);
|
||||
}
|
||||
|
||||
std::unique_ptr<Fluxmap> AmigaEncoder::encode(
|
||||
int physicalTrack, int physicalSide, const SectorSet& allSectors)
|
||||
{
|
||||
if ((physicalTrack < 0) || (physicalTrack >= AMIGA_TRACKS_PER_DISK))
|
||||
return std::unique_ptr<Fluxmap>();
|
||||
|
||||
int bitsPerRevolution = 200000.0 / clockRateUs;
|
||||
std::vector<bool> bits(bitsPerRevolution);
|
||||
unsigned cursor = 0;
|
||||
|
||||
fillBitmapTo(bits, cursor, postIndexGapMs * 1000 / clockRateUs, { true, false });
|
||||
lastBit = false;
|
||||
|
||||
for (int sectorId=0; sectorId<AMIGA_SECTORS_PER_TRACK; sectorId++)
|
||||
{
|
||||
const auto& sectorData = allSectors.get(physicalTrack, physicalSide, sectorId);
|
||||
write_sector(bits, cursor, sectorData);
|
||||
}
|
||||
|
||||
if (cursor >= bits.size())
|
||||
Error() << "track data overrun";
|
||||
fillBitmapTo(bits, cursor, bits.size(), { true, false });
|
||||
|
||||
std::unique_ptr<Fluxmap> fluxmap(new Fluxmap);
|
||||
fluxmap->appendBits(bits, clockRateUs*1e3);
|
||||
return fluxmap;
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ std::unique_ptr<Fluxmap> BrotherEncoder::encode(
|
||||
write_sector_data(bits, cursor, sectorData->data);
|
||||
}
|
||||
|
||||
if (cursor > bits.size())
|
||||
if (cursor >= bits.size())
|
||||
Error() << "track data overrun";
|
||||
fillBitmapTo(bits, cursor, bits.size(), { true, false });
|
||||
|
||||
|
||||
@@ -73,8 +73,10 @@ const FluxPattern FM_TRS80DAM2_PATTERN(16, 0xf56c);
|
||||
* encoding (you can't do 10 00). So this can't be spoofed by user data.
|
||||
*
|
||||
* shifted: 10 00 10 01 00 01 00 1
|
||||
*
|
||||
* It's repeated three times.
|
||||
*/
|
||||
const FluxPattern MFM_PATTERN(16, 0x4489);
|
||||
const FluxPattern MFM_PATTERN(48, 0x448944894489LL);
|
||||
|
||||
const FluxMatchers ANY_RECORD_PATTERN(
|
||||
{
|
||||
@@ -100,7 +102,8 @@ AbstractDecoder::RecordType IbmDecoder::advanceToNextRecord()
|
||||
if (_currentHeaderLength > 0)
|
||||
readRawBits(_currentHeaderLength*16);
|
||||
auto idbits = readRawBits(16);
|
||||
uint8_t id = decodeFmMfm(idbits).slice(0, 1)[0];
|
||||
const Bytes idbytes = decodeFmMfm(idbits);
|
||||
uint8_t id = idbytes.slice(0, 1)[0];
|
||||
seek(here);
|
||||
|
||||
switch (id)
|
||||
|
||||
235
arch/ibm/encoder.cc
Normal file
235
arch/ibm/encoder.cc
Normal file
@@ -0,0 +1,235 @@
|
||||
#include "globals.h"
|
||||
#include "record.h"
|
||||
#include "decoders/decoders.h"
|
||||
#include "encoders/encoders.h"
|
||||
#include "ibm.h"
|
||||
#include "crc.h"
|
||||
#include "sectorset.h"
|
||||
#include "writer.h"
|
||||
#include "fmt/format.h"
|
||||
#include <ctype.h>
|
||||
|
||||
/* IAM record separator:
|
||||
* 0xC2 is:
|
||||
* data: 1 1 0 0 0 0 1 0 = 0xc2
|
||||
* mfm: 01 01 00 10 10 10 01 00 = 0x5254
|
||||
* special: 01 01 00 10 00 10 01 00 = 0x5224
|
||||
*/
|
||||
#define MFM_IAM_SEPARATOR 0x5224
|
||||
|
||||
/* FM IAM record:
|
||||
* flux: XXXX-XXX-XXXX-X- = 0xf77a
|
||||
* clock: X X - X - X X X = 0xd7
|
||||
* data: X X X X X X - - = 0xfc
|
||||
*/
|
||||
#define FM_IAM_RECORD 0xf77a
|
||||
|
||||
/* MFM IAM record:
|
||||
* data: 1 1 1 1 1 1 0 0 = 0xfc
|
||||
* flux: 01 01 01 01 01 01 00 10 = 0x5552
|
||||
*/
|
||||
#define MFM_IAM_RECORD 0x5552
|
||||
|
||||
/* MFM record separator:
|
||||
* 0xA1 is:
|
||||
* data: 1 0 1 0 0 0 0 1 = 0xa1
|
||||
* mfm: 01 00 01 00 10 10 10 01 = 0x44a9
|
||||
* special: 01 00 01 00 10 00 10 01 = 0x4489
|
||||
* ^^^^^
|
||||
* When shifted out of phase, the special 0xa1 byte becomes an illegal
|
||||
* encoding (you can't do 10 00). So this can't be spoofed by user data.
|
||||
*
|
||||
* shifted: 10 00 10 01 00 01 00 1
|
||||
*
|
||||
* It's repeated three times.
|
||||
*/
|
||||
#define MFM_RECORD_SEPARATOR 0x4489
|
||||
#define MFM_RECORD_SEPARATOR_BYTE 0xa1
|
||||
|
||||
/* MFM IDAM byte:
|
||||
* data: 1 1 1 1 1 1 1 0 = 0xfe
|
||||
* mfm: 01 01 01 01 01 01 01 00 = 0x5554
|
||||
*/
|
||||
|
||||
/* MFM DAM byte:
|
||||
* data: 1 1 1 1 1 0 1 1 = 0xfb
|
||||
* mfm: 01 01 01 01 01 00 01 01 = 0x5545
|
||||
*/
|
||||
|
||||
static int charToInt(char c)
|
||||
{
|
||||
if (isdigit(c))
|
||||
return c - '0';
|
||||
return 10 + tolower(c) - 'a';
|
||||
}
|
||||
|
||||
void IbmEncoder::writeRawBits(uint32_t data, int width)
|
||||
{
|
||||
_cursor += width;
|
||||
_lastBit = data & 1;
|
||||
for (int i=0; i<width; i++)
|
||||
{
|
||||
unsigned pos = _cursor - i - 1;
|
||||
if (pos < _bits.size())
|
||||
_bits[pos] = data & 1;
|
||||
data >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
void IbmEncoder::writeBytes(const Bytes& bytes)
|
||||
{
|
||||
if (_parameters.useFm)
|
||||
encodeFm(_bits, _cursor, bytes);
|
||||
else
|
||||
encodeMfm(_bits, _cursor, bytes, _lastBit);
|
||||
}
|
||||
|
||||
void IbmEncoder::writeBytes(int count, uint8_t byte)
|
||||
{
|
||||
Bytes bytes = { byte };
|
||||
for (int i=0; i<count; i++)
|
||||
writeBytes(bytes);
|
||||
}
|
||||
|
||||
static uint8_t decodeUint16(uint16_t raw)
|
||||
{
|
||||
Bytes b;
|
||||
ByteWriter bw(b);
|
||||
bw.write_be16(raw);
|
||||
return decodeFmMfm(b.toBits())[0];
|
||||
}
|
||||
|
||||
std::unique_ptr<Fluxmap> IbmEncoder::encode(
|
||||
int physicalTrack, int physicalSide, const SectorSet& allSectors)
|
||||
{
|
||||
double clockRateUs = 1e3 / _parameters.clockRateKhz;
|
||||
if (!_parameters.useFm)
|
||||
clockRateUs /= 2.0;
|
||||
int bitsPerRevolution = (_parameters.trackLengthMs * 1000.0) / clockRateUs;
|
||||
_bits.resize(bitsPerRevolution);
|
||||
_cursor = 0;
|
||||
|
||||
uint8_t idamUnencoded = decodeUint16(_parameters.idamByte);
|
||||
uint8_t damUnencoded = decodeUint16(_parameters.damByte);
|
||||
|
||||
uint8_t sectorSize = 0;
|
||||
{
|
||||
int s = _parameters.sectorSize >> 7;
|
||||
while (s > 1)
|
||||
{
|
||||
s >>= 1;
|
||||
sectorSize += 1;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t gapFill = _parameters.useFm ? 0x00 : 0x4e;
|
||||
|
||||
writeBytes(_parameters.gap0, gapFill);
|
||||
if (_parameters.emitIam)
|
||||
{
|
||||
writeBytes(_parameters.useFm ? 6 : 12, 0x00);
|
||||
if (!_parameters.useFm)
|
||||
{
|
||||
for (int i=0; i<3; i++)
|
||||
writeRawBits(MFM_IAM_SEPARATOR, 16);
|
||||
}
|
||||
writeRawBits(_parameters.useFm ? FM_IAM_RECORD : MFM_IAM_RECORD, 16);
|
||||
writeBytes(_parameters.gap1, gapFill);
|
||||
}
|
||||
|
||||
bool first = true;
|
||||
for (char sectorChar : _parameters.sectorSkew)
|
||||
{
|
||||
int sectorId = charToInt(sectorChar);
|
||||
if (!first)
|
||||
writeBytes(_parameters.gap3, gapFill);
|
||||
first = false;
|
||||
|
||||
const auto& sectorData = allSectors.get(physicalTrack, physicalSide, sectorId);
|
||||
if (!sectorData)
|
||||
Error() << fmt::format("format tried to find sector {} which wasn't in the input file", sectorId);
|
||||
|
||||
/* Writing the sector and data records are fantastically annoying.
|
||||
* The CRC is calculated from the *very start* of the record, and
|
||||
* include the malformed marker bytes. Our encoder doesn't know
|
||||
* about this, of course, with the result that we have to construct
|
||||
* the unencoded header, calculate the checksum, and then use the
|
||||
* same logic to emit the bytes which require special encoding
|
||||
* before encoding the rest of the header normally. */
|
||||
|
||||
{
|
||||
Bytes header;
|
||||
ByteWriter bw(header);
|
||||
|
||||
writeBytes(_parameters.useFm ? 6 : 12, 0x00);
|
||||
if (!_parameters.useFm)
|
||||
{
|
||||
for (int i=0; i<3; i++)
|
||||
bw.write_8(MFM_RECORD_SEPARATOR_BYTE);
|
||||
}
|
||||
bw.write_8(idamUnencoded);
|
||||
bw.write_8(sectorData->logicalTrack);
|
||||
bw.write_8(sectorData->logicalSide);
|
||||
bw.write_8(sectorData->logicalSector + _parameters.startSectorId);
|
||||
bw.write_8(sectorSize);
|
||||
uint16_t crc = crc16(CCITT_POLY, header);
|
||||
bw.write_be16(crc);
|
||||
|
||||
int conventionalHeaderStart = 0;
|
||||
if (!_parameters.useFm)
|
||||
{
|
||||
for (int i=0; i<3; i++)
|
||||
writeRawBits(MFM_RECORD_SEPARATOR, 16);
|
||||
conventionalHeaderStart += 3;
|
||||
|
||||
}
|
||||
writeRawBits(_parameters.idamByte, 16);
|
||||
conventionalHeaderStart += 1;
|
||||
|
||||
writeBytes(header.slice(conventionalHeaderStart));
|
||||
}
|
||||
|
||||
writeBytes(_parameters.gap2, gapFill);
|
||||
|
||||
{
|
||||
Bytes data;
|
||||
ByteWriter bw(data);
|
||||
|
||||
writeBytes(_parameters.useFm ? 6 : 12, 0x00);
|
||||
if (!_parameters.useFm)
|
||||
{
|
||||
for (int i=0; i<3; i++)
|
||||
bw.write_8(MFM_RECORD_SEPARATOR_BYTE);
|
||||
}
|
||||
bw.write_8(damUnencoded);
|
||||
|
||||
Bytes truncatedData = sectorData->data.slice(0, _parameters.sectorSize);
|
||||
bw += truncatedData;
|
||||
uint16_t crc = crc16(CCITT_POLY, data);
|
||||
bw.write_be16(crc);
|
||||
|
||||
int conventionalHeaderStart = 0;
|
||||
if (!_parameters.useFm)
|
||||
{
|
||||
for (int i=0; i<3; i++)
|
||||
writeRawBits(MFM_RECORD_SEPARATOR, 16);
|
||||
conventionalHeaderStart += 3;
|
||||
|
||||
}
|
||||
writeRawBits(_parameters.damByte, 16);
|
||||
conventionalHeaderStart += 1;
|
||||
|
||||
writeBytes(data.slice(conventionalHeaderStart));
|
||||
}
|
||||
}
|
||||
|
||||
if (_cursor >= _bits.size())
|
||||
Error() << "track data overrun";
|
||||
while (_cursor < _bits.size())
|
||||
writeBytes(1, gapFill);
|
||||
|
||||
std::unique_ptr<Fluxmap> fluxmap(new Fluxmap);
|
||||
fluxmap->appendBits(_bits, clockRateUs*1e3);
|
||||
return fluxmap;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define IBM_H
|
||||
|
||||
#include "decoders/decoders.h"
|
||||
#include "encoders/encoders.h"
|
||||
|
||||
/* IBM format (i.e. ordinary PC floppies). */
|
||||
|
||||
@@ -31,68 +32,68 @@ struct IbmIdam
|
||||
class IbmDecoder : public AbstractDecoder
|
||||
{
|
||||
public:
|
||||
IbmDecoder(unsigned sectorBase, bool ignoreSideByte=false):
|
||||
IbmDecoder(unsigned sectorBase, bool ignoreSideByte=false,
|
||||
const std::set<unsigned> requiredSectors=std::set<unsigned>()):
|
||||
_sectorBase(sectorBase),
|
||||
_ignoreSideByte(ignoreSideByte)
|
||||
_ignoreSideByte(ignoreSideByte),
|
||||
_requiredSectors(requiredSectors)
|
||||
{}
|
||||
|
||||
RecordType advanceToNextRecord();
|
||||
void decodeSectorRecord();
|
||||
void decodeDataRecord();
|
||||
|
||||
std::set<unsigned> requiredSectors(Track& track) const
|
||||
{ return _requiredSectors; }
|
||||
|
||||
private:
|
||||
unsigned _sectorBase;
|
||||
bool _ignoreSideByte;
|
||||
std::set<unsigned> _requiredSectors;
|
||||
unsigned _currentSectorSize;
|
||||
unsigned _currentHeaderLength;
|
||||
};
|
||||
|
||||
#if 0
|
||||
class AbstractIbmDecoder : public AbstractSoftSectorDecoder
|
||||
struct IbmParameters
|
||||
{
|
||||
int trackLengthMs;
|
||||
int sectorSize;
|
||||
bool emitIam;
|
||||
int startSectorId;
|
||||
int clockRateKhz;
|
||||
bool useFm;
|
||||
uint16_t idamByte;
|
||||
uint16_t damByte;
|
||||
int gap0;
|
||||
int gap1;
|
||||
int gap2;
|
||||
int gap3;
|
||||
std::string sectorSkew;
|
||||
};
|
||||
|
||||
class IbmEncoder : public AbstractEncoder
|
||||
{
|
||||
public:
|
||||
AbstractIbmDecoder(unsigned sectorIdBase):
|
||||
_sectorIdBase(sectorIdBase)
|
||||
{}
|
||||
virtual ~AbstractIbmDecoder() {}
|
||||
IbmEncoder(const IbmParameters& parameters):
|
||||
_parameters(parameters)
|
||||
{}
|
||||
|
||||
SectorVector decodeToSectors(const RawRecordVector& rawRecords, unsigned physicalTrack, unsigned physicalSide);
|
||||
virtual ~IbmEncoder() {}
|
||||
|
||||
protected:
|
||||
virtual int skipHeaderBytes() const = 0;
|
||||
public:
|
||||
std::unique_ptr<Fluxmap> encode(int physicalTrack, int physicalSide, const SectorSet& allSectors);
|
||||
|
||||
private:
|
||||
unsigned _sectorIdBase;
|
||||
void writeRawBits(uint32_t data, int width);
|
||||
void writeBytes(const Bytes& bytes);
|
||||
void writeBytes(int count, uint8_t value);
|
||||
void writeSync();
|
||||
|
||||
private:
|
||||
IbmParameters _parameters;
|
||||
std::vector<bool> _bits;
|
||||
unsigned _cursor;
|
||||
bool _lastBit;
|
||||
};
|
||||
|
||||
class IbmFmDecoder : public AbstractIbmDecoder
|
||||
{
|
||||
public:
|
||||
IbmFmDecoder(unsigned sectorIdBase):
|
||||
AbstractIbmDecoder(sectorIdBase)
|
||||
{}
|
||||
|
||||
int recordMatcher(uint64_t fifo) const;
|
||||
|
||||
protected:
|
||||
int skipHeaderBytes() const
|
||||
{ return 0; }
|
||||
};
|
||||
|
||||
class IbmMfmDecoder : public AbstractIbmDecoder
|
||||
{
|
||||
public:
|
||||
IbmMfmDecoder(unsigned sectorIdBase):
|
||||
AbstractIbmDecoder(sectorIdBase)
|
||||
{}
|
||||
|
||||
nanoseconds_t guessClock(Fluxmap& fluxmap) const;
|
||||
int recordMatcher(uint64_t fifo) const;
|
||||
|
||||
protected:
|
||||
int skipHeaderBytes() const
|
||||
{ return 3; }
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -184,3 +184,26 @@ void MacintoshDecoder::decodeDataRecord()
|
||||
_sector->data.clear();
|
||||
_sector->data.writer().append(userData.slice(12, 512)).append(userData.slice(0, 12));
|
||||
}
|
||||
|
||||
std::set<unsigned> MacintoshDecoder::requiredSectors(Track& track) const
|
||||
{
|
||||
int count;
|
||||
if (track.physicalTrack < 16)
|
||||
count = 12;
|
||||
else if (track.physicalTrack < 32)
|
||||
count = 11;
|
||||
else if (track.physicalTrack < 48)
|
||||
count = 10;
|
||||
else if (track.physicalTrack < 64)
|
||||
count = 9;
|
||||
else
|
||||
count = 8;
|
||||
|
||||
std::set<unsigned> sectors;
|
||||
do
|
||||
sectors.insert(count);
|
||||
while (count--);
|
||||
return sectors;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -18,6 +18,8 @@ public:
|
||||
RecordType advanceToNextRecord();
|
||||
void decodeSectorRecord();
|
||||
void decodeDataRecord();
|
||||
|
||||
std::set<unsigned> requiredSectors(Track& track) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
BIN
doc/Index_sensor_mod_FDD_1.1.pdf
Normal file
BIN
doc/Index_sensor_mod_FDD_1.1.pdf
Normal file
Binary file not shown.
184
doc/building.md
184
doc/building.md
@@ -25,6 +25,8 @@ This is the physical stuff you'll need.
|
||||
connector](https://eu.mouser.com/ProductDetail/Amphenol-FCI/86130342114345E1LF?qs=%2Fha2pyFadug%252BpMTyxmFhglPPVKuWXYuFpPNgq%252BsrzhDnXxo8B28k7UCGc7F%2FXjsi)
|
||||
(or one of the other myriad compatible connectors; there's a billion).
|
||||
|
||||
- A floppy drive cable, preferably one with two connectors and a twist.
|
||||
|
||||
- A suitable power supply. 3.5" floppy drives use 5V at about an amp
|
||||
(usually less) --- sadly, too much to power from USB. 5.25" floppy drives
|
||||
also require 12V. An old but decent quality PC power supply is ideal, as
|
||||
@@ -48,7 +50,7 @@ All you need to do is attach your chosen connector to the board. You'll need
|
||||
to make sure that pin 2 on the cable is connected to pin 2.7 on the board,
|
||||
and pin 34 to pin 1.7 on the board (and of course all the ones in between).
|
||||
Apart from grounding the board (see below), this is literally all there is to
|
||||
it.
|
||||
it. The actual pinout is described in detail below.
|
||||
|
||||
The pads are small, but soldering them isn't too bad with a needle-nosed
|
||||
soldering iron tip.
|
||||
@@ -173,6 +175,7 @@ pattern. Press and hold the little button near the light for five seconds
|
||||
until the light stays solidly on. Now you should be able to acquire
|
||||
the port and proceed normally.
|
||||
|
||||
|
||||
## Building the client
|
||||
|
||||
The client software is where the intelligence, such as it is, is. It's pretty
|
||||
@@ -181,12 +184,12 @@ well, although on Windows it'll need MSYS2 and mingw32. You'll need to
|
||||
install some support packages.
|
||||
|
||||
- For Linux (this is Ubuntu, but this should apply to Debian too):
|
||||
`ninja-build`, `libusb-1.0-0-dev`, `libsqlite3-dev`.
|
||||
- For OSX with Homebrew: `ninja`.
|
||||
`ninja-build`, `libusb-1.0-0-dev`, `libsqlite3-dev`.
|
||||
- For OSX with Homebrew: `ninja`, `libusb`, `pkg-config`, `sqlite`.
|
||||
- For Windows with MSYS2: `make`, `ninja`, `mingw-w64-i686-libusb`,
|
||||
`mingw-w64-i686-sqlite3`, `mingw-w64-i686-zlib`, `mingw-w64-i686-gcc`.
|
||||
`mingw-w64-i686-sqlite3`, `mingw-w64-i686-zlib`, `mingw-w64-i686-gcc`.
|
||||
|
||||
These lists are not necessarily exhaustive --- plaese [get in
|
||||
These lists are not necessarily exhaustive --- please [get in
|
||||
touch](https://github.com/davidgiven/fluxengine/issues/new) if I've missed
|
||||
anything.
|
||||
|
||||
@@ -197,11 +200,176 @@ dependencies and you should be able to put it anywhere.
|
||||
If it doesn't build, please [get in
|
||||
touch](https://github.com/davidgiven/fluxengine/issues/new).
|
||||
|
||||
|
||||
## Connecting it up
|
||||
|
||||
You should now have a working board, so it's time to test it.
|
||||
|
||||
1. Plug the motherboard end of your floppy disk cable into the FluxEngine.
|
||||
|
||||
The **red stripe goes on the right**. The **lower set of
|
||||
holes connect to the board**. See the pinout below.
|
||||
|
||||
If you're using header pins, the upper row of holes in the connector
|
||||
should overhang the edge of the board. If you're using a floppy drive
|
||||
motherboard connector, you're golden, of course (unless you have one of
|
||||
those annoying unkeyed cables, or have accidentally soldered the
|
||||
connector on in the wrong place --- don't laugh, I've done it.)
|
||||
|
||||
2. Plug the drive end of your floppy disk cable into the drive (or drives).
|
||||
|
||||
Floppy disk cables typically have [two pairs of floppy disk drive
|
||||
connectors with a twist between
|
||||
them](http://www.nullmodem.com/Floppy.htm). (Each pair has one connector
|
||||
for a 3.5" drive and a different one for a 5.25" drive.) (Some cables
|
||||
are cheap and just have the 3.5" connectors. Some are _very_ cheap and
|
||||
have a single 3.5" connector, after the twist.)
|
||||
|
||||
If you have **two** drives, plug them into both connectors. FluxEngine,
|
||||
sadly, non-standard disk numbering (there are reasons). Drive 0 is the
|
||||
one nearest the motherboard; that is, before the twist. Drive 1 is the
|
||||
one at the end of the cable; that is, after the twist. Drive 0 is the
|
||||
default. You can tell the client to select drive 1 by using `-s :d=1`.
|
||||
|
||||
If you have **one** drive, you may plug it into _either_ connector.
|
||||
FluxEngine will autodetect it and treat it as drive 0. However, you'll
|
||||
get the most reliable electrical signal if you plug it in at the end of
|
||||
the cable.
|
||||
|
||||
**A note on termination:** some 5.25" drives require jumper configuration
|
||||
to tell them whether they're at the end of the cable or in the middle of
|
||||
the cable. 3.5" drives don't, and my 5.25" drives don't, so I can't
|
||||
advise there. Consult your drive datasheet for details.
|
||||
|
||||
3. **Important.** Make sure that no disk you care about is in the drive.
|
||||
(Because if your wiring is wrong and a disk is inserted, you'll corrupt
|
||||
it.)
|
||||
|
||||
4. Connect the floppy drive to power. Nothing should happen. If you've
|
||||
connected something in backwards, you'll see the drive light up, the motor
|
||||
start, and if you didn't take the disk out, one track has just been wiped.
|
||||
If this happens, check your wiring.
|
||||
|
||||
5. Strip off the little piece of protective plastic on the USB socket on the
|
||||
board --- the little socket at the end, not the big programmer plug.
|
||||
|
||||
6. Connect the FluxEngine to your PC via USB.
|
||||
|
||||
7. Insert a scratch disk and do `fluxengine rpm` from the shell. The motor
|
||||
should work and it'll tell you that the disk is spinning at about 300
|
||||
rpm for a 3.5" disk, or 360 rpm for a 5.25" disk. If it doesn't, please
|
||||
[get in touch](https://github.com/davidgiven/fluxengine/issues/new).
|
||||
|
||||
8. Do `fluxengine test bandwidth` from the shell. It'll measure your USB
|
||||
bandwidth. Ideally you should be getting above 900kB/s in both directions.
|
||||
FluxEngine needs about 400kB/s for a DD disk and about 850kB/s for a HD
|
||||
disk, so if you're getting less than this, try a different USB port.
|
||||
|
||||
9. Insert a standard PC formatted floppy disk into the drive (probably a good
|
||||
idea to remove the old disk first). Then do `fluxengine read ibm`. It
|
||||
should read the disk, emitting copious diagnostics, and spit out an
|
||||
`ibm.img` file containing the decoded disk image (either 1440kB or 720kB
|
||||
depending).
|
||||
|
||||
10. Profit!
|
||||
|
||||
## Technical details
|
||||
|
||||
The board pinout and the way it's connected to the floppy bus is described
|
||||
below.
|
||||
|
||||
```ditaa
|
||||
:-E -s 0.75
|
||||
+-----+
|
||||
|||||||
|
||||
+----+-----+----+
|
||||
+cAAA +
|
||||
+ Debug board +
|
||||
+----+-----+----+
|
||||
+ GND|cDDD | VDD+
|
||||
+----+ +----+
|
||||
INDEX300 ---+ 3.0| | GND+--------------------------+
|
||||
+----+ +----+ +--+--+ |
|
||||
INDEX360 ---+ 3.1| | 1.7+------ DISKCHG --+34+33+--+
|
||||
+----+ +----+ +--+--+
|
||||
+ 3.2| | 1.6+------- SIDE1 ---+32+31+
|
||||
+----+ +----+ +--+--+
|
||||
+ 3.3| | 1.5+------- RDATA ---+30+29+
|
||||
+----+ +----+ +--+--+
|
||||
+ 3.4| | 1.4+-------- WPT ----+28+27+
|
||||
+----+ +----+ +--+--+
|
||||
+ 3.5| | 1.3+------- TRK00 ---+26+25+
|
||||
+----+ +----+ +--+--+
|
||||
+ 3.6| | 1.2+------- WGATE ---+24+23+
|
||||
+----+ +----+ +--+--+
|
||||
+ 3.7| | 1.1+------- WDATA ---+22+21+
|
||||
+----+ +----+ +--+--+
|
||||
+15.0| | 1.0+------- STEP ----+20+19+
|
||||
+----+ +----+ +--+--+
|
||||
+15.1| |12.0+-------- DIR ----+18+17+
|
||||
+----+ +----+ +--+--+
|
||||
+15.2| |12.1+------- MOTEB ---+16+15+
|
||||
+----+ +----+ +--+--+
|
||||
+15.3| |12.2+------- DRVSA ---+14+13+
|
||||
+----+ +----+ +--+--+
|
||||
+15.4| |12.3+------- DRVSB ---+12+11+
|
||||
+----+ +----+ +--+--+
|
||||
+15.5| |12.4+------- MOTEA ---+10+9 +
|
||||
+----+ +----+ +--+--+
|
||||
+ 0.0| |12.5+------- INDEX ---+8 +7 +
|
||||
+----+ +----+ +--+--+
|
||||
+ 0.1| |12.6+-------- n/c ----+6 +5 +
|
||||
+----+ +----+ +--+--+
|
||||
+ 0.2| |12.7+- TX --- n/c ----+4 +3 +
|
||||
+----+ +----+ +--+--+
|
||||
+ 0.3| | 2.7+------- REDWC ---+2 +1 +
|
||||
+----+ +----+ +--+--+
|
||||
+ 0.4| | 2.6+
|
||||
+----+ +----+ FDD socket
|
||||
+ 0.5| | 2.5+
|
||||
+----+ +----+
|
||||
+ 0.6| | 2.4+ TX: debug UART from board
|
||||
+----+ +----+
|
||||
+ 0.7| | 2.3+
|
||||
+----+ +----+
|
||||
+ RST| | 2.2+
|
||||
+----+ +----+
|
||||
+ GND| | 2.1+
|
||||
+----+ USB +----+
|
||||
+ VDD+-----+ 2.0+
|
||||
+----+-----+----+
|
||||
PSoC5 board
|
||||
```
|
||||
|
||||
Notes:
|
||||
|
||||
- `TX` is the debug UART port. It's on pin 12.7 because the board routes it
|
||||
to the USB serial port on the programmer, so you can get debug information
|
||||
from the FluxEngine by just plugging the programming end into a USB port
|
||||
and using a serial terminal at 115200 baud. If you solder a floppy drive
|
||||
connector on, then it'll end up connected to pin 4 of the floppy drive bus,
|
||||
which is usually not connected. It's possible that some floppy drives do,
|
||||
in fact, use this pin. You may wish to remove pin 4 from the floppy drive
|
||||
socket before attaching it to the FluxEngine to make sure that this pin is
|
||||
not connected; however, so far I have not found any drives for which this
|
||||
is necessary. If you do find one, _please_ [get in
|
||||
touch](https://github.com/davidgiven/fluxengine/issues/new) so I can
|
||||
document it.
|
||||
|
||||
- The `GND` pin only really needs to be connected to one of the floppy bus
|
||||
ground pins; pin 33 is the closest. For extra safety, you can bridge all
|
||||
the odd numbered pins together and ground them all if you like.
|
||||
|
||||
- `INDEX300` and `INDEX360` are optional output pins which generate fake
|
||||
timing pulses for 300 and 360 RPM drives. These are useful for certain
|
||||
rather exotic things. See the section on flippy disks [in the FAQ](faq.md)
|
||||
for more details; you can normally ignore these.
|
||||
|
||||
## Next steps
|
||||
|
||||
The board's now assembled and programmed. Plug it into your drive, strip the
|
||||
plastic off the little USB connector and plug that into your computer, and
|
||||
you're ready to start using it.
|
||||
You should now be ready to go. You'll want to read [the client
|
||||
documentation](using.md) for information about how to actually do interesting
|
||||
things.
|
||||
|
||||
I _do_ make updates to the firmware whenever necessary, so you may need to
|
||||
reprogram it at intervals; you may want to take this into account if you
|
||||
|
||||
@@ -10,7 +10,7 @@ Bizarrely, the data in each sector is stored with all the odd bits first, and
|
||||
then all the even bits. This is tied into the checksum algorithm, which is
|
||||
distinctly subpar and not particularly good at detecting errors.
|
||||
|
||||
Reading discs
|
||||
Reading disks
|
||||
-------------
|
||||
|
||||
Just do:
|
||||
@@ -34,6 +34,28 @@ You will end up with a 929280 byte long image which you probably _can't_ use
|
||||
in an emulator; each sector will contain the 512 bytes of user payload
|
||||
followed by the 16 bytes of metadata.
|
||||
|
||||
Writing disks
|
||||
-------------
|
||||
|
||||
Just do:
|
||||
|
||||
```
|
||||
fluxengine write amiga -i amiga.adf
|
||||
```
|
||||
|
||||
This will rake a normal 901120 byte long ADF file and write it to a DD disk.
|
||||
Note that writing to an HD disk will probably not work (this will depend on
|
||||
your drive and disk and potential FluxEngine bugs I'm still working on ---
|
||||
please [get in touch](https://github.com/davidgiven/fluxengine/issues/new) if
|
||||
you have any insight here).
|
||||
|
||||
If you want to write the metadata as well, specify a 528 byte sector size for
|
||||
the output image and supply a 929280 byte long file as described above.
|
||||
|
||||
```
|
||||
fluxengine write amiga -i amiga.adf:b=528
|
||||
```
|
||||
|
||||
Useful references
|
||||
-----------------
|
||||
|
||||
|
||||
@@ -14,10 +14,12 @@ Apparently about 20% of Brother word processors have alignment issues which
|
||||
means that the disks can't be read by FluxEngine (because the tracks on the
|
||||
disk don't line up with the position of the head in a PC drive). The word
|
||||
processors themselves solved this by microstepping until they found where the
|
||||
real track is, but normal PC drives aren't capable of doing this.
|
||||
Particularly with the 120kB disks, you might want to fiddle with the start
|
||||
track (e.g. `:t=0-79x2`) to get a clean read. Keep an eye on the bad sector
|
||||
map that's dumped at the end of a read.
|
||||
real track is, but normal PC drives aren't capable of doing this. Particularly
|
||||
with the 120kB disks, you might want to fiddle with the start track (e.g.
|
||||
`:t=0-79x2`) to get a clean read. Keep an eye on the bad sector map that's
|
||||
dumped at the end of a read. My word processor likes to put logical track 0 on
|
||||
physical track 3, which means that logical track 77 is on physical track 80;
|
||||
luckily my PC drive can access track 80.
|
||||
|
||||
Using FluxEngine to *write* disks isn't a problem, so the
|
||||
simplest solution is to use FluxEngine to create a new disk, with the tracks
|
||||
@@ -30,7 +32,7 @@ If you find one of these misaligned disks then *please* [get in
|
||||
touch](https://github.com/davidgiven/fluxengine/issues/new); I want to
|
||||
investigate.
|
||||
|
||||
Reading discs
|
||||
Reading disks
|
||||
-------------
|
||||
|
||||
Just do:
|
||||
@@ -41,7 +43,7 @@ fluxengine read brother
|
||||
|
||||
You should end up with a `brother.img` which is 239616 bytes long.
|
||||
|
||||
Writing discs
|
||||
Writing disks
|
||||
-------------
|
||||
|
||||
Just do:
|
||||
@@ -53,6 +55,27 @@ fluxengine write brother
|
||||
...and it'll write a `brother.img` file which is 239616 bytes long to the
|
||||
disk. (Use `-i` to specify a different input filename.)
|
||||
|
||||
Dealing with misaligned disks
|
||||
-----------------------------
|
||||
|
||||
While FluxEngine can't read misaligned disks directly, Brother word processors
|
||||
_can_. If you have access to a compatible word processor, there's a fairly
|
||||
simple workaround to allow you to extract the data:
|
||||
|
||||
1. Format a disk using FluxEngine (by simply writing a blank filesystem image
|
||||
to a disk). This will have the correct alignment to work on a PC drive.
|
||||
|
||||
2. Use a word processor to copy the misaligned disk to the newly formatted
|
||||
disk. The machine will happily adjust itself to both sets of alignments.
|
||||
|
||||
3. Use FluxEngine to read the data off the correctly aligned disk.
|
||||
|
||||
I realise this is rather unsatisfactory, as the Brother hardware is becoming
|
||||
rarer and they cope rather badly with damaged disks, but this is a limitation
|
||||
of the hardware of normal PC drives. (It _is_ possible to deliberately misalign
|
||||
a drive to make it match up with a bad disk, but this is for experts only --- I
|
||||
wouldn't dare.)
|
||||
|
||||
Low level format
|
||||
----------------
|
||||
|
||||
@@ -60,14 +83,6 @@ The drive is a single-sided 3.5" drive spinning at not 300 rpm (I don't know
|
||||
the precise speed yet but FluxEngine doesn't care). The 240kB disks have 78
|
||||
tracks and the 120kB disks have 39.
|
||||
|
||||
The Brother drive alignment is kinda variable; when you put the disk in the
|
||||
drive it seeks all the way to physical track 0 and then starts searching for
|
||||
something which looks like data. My machine likes to put logical track 0 on
|
||||
physical track 3. FluxEngine puts logical track 0 on physical track 0 for
|
||||
simplicity, which works fine (at least on my machine). If this doesn't work
|
||||
for you, [get in touch](https://github.com/davidgiven/fluxengine/issues/new);
|
||||
there are potential workarounds.
|
||||
|
||||
Each track has 12 256-byte sectors. The drive ignores the index hole so they're
|
||||
lined up all anyhow. As FluxEngine can only read from index to index, it
|
||||
actually reads two complete revolutions and reassembles the sectors from that.
|
||||
@@ -138,7 +153,8 @@ mcopy -i brother.img ::brother.doc linux.doc
|
||||
```
|
||||
|
||||
The word processor checks the media byte, unfortunately, so you'll need to
|
||||
change it back to 0x58 before writing an image to disk.
|
||||
change it back to 0x58 before writing an image to disk. Just run
|
||||
`brother240tool` on the image again and it will flip it back.
|
||||
|
||||
The file format is not WP-1, and currently remains completely unknown,
|
||||
although it's probably related. If anyone knows anything about this, please
|
||||
|
||||
152
doc/disk-ibm.md
Normal file
152
doc/disk-ibm.md
Normal file
@@ -0,0 +1,152 @@
|
||||
Disk: Generic IBM
|
||||
=================
|
||||
|
||||
IBM scheme disks are _the_ most common disk format, ever. They're used by a
|
||||
huge variety of different systems, and they come in a huge variety of different
|
||||
forms, but they're all fundamentally the same: either FM or MFM, either single
|
||||
or double sided, with distinct sector header and data records and no sector
|
||||
metadata. Systems which use IBM scheme disks include but are not limited to:
|
||||
|
||||
- IBM PCs (naturally)
|
||||
- Atari ST
|
||||
- late era Apple machines
|
||||
- Acorn machines
|
||||
- the TRS-80
|
||||
- late era Commodore machines (the 1571 and so on)
|
||||
- most CP/M machines
|
||||
- etc
|
||||
|
||||
FluxEngine supports reading these. However, some variants are more peculiar
|
||||
than others, and as a result there are specific decoders which set the defaults
|
||||
correctly for certain formats (for example: on PC disks the sector numbers
|
||||
start from 1, but on [Acorn](disk-acorndfs.md) disks they start from 0). The
|
||||
IBM decoder described here is the generic one, and is suited for 'conventional'
|
||||
PC disks. While you can read all the variant formats with it if you use the
|
||||
right set of arguments, it's easier to use the specific decoder.
|
||||
|
||||
The generic decoder is mostly self-configuring, and will detect the format of
|
||||
your disk for you.
|
||||
|
||||
|
||||
Reading disks
|
||||
-------------
|
||||
|
||||
Just do:
|
||||
|
||||
fluxengine read ibm
|
||||
|
||||
...and you'll end up with an `ibm.img` file. This should work on most PC disks
|
||||
(including FM 360kB disks, 3.5" 1440kB disks, 5.25" 1200kB disks, etc.) The size
|
||||
of the disk image will vary depending on the format.
|
||||
|
||||
Configuration options you'll want include:
|
||||
|
||||
- `--ibm-sector-id-base=N`: specifies the ID of the first sector; this defaults
|
||||
to 1. Some formats (like the Acorn ones) start at 0. This can't be
|
||||
autodetected because FluxEngine can't distinguish between a disk which
|
||||
starts at sector 1 and a disk which starts at sector 0 but all the sector
|
||||
0s are missing.
|
||||
|
||||
- `--ibm-ignore-side-byte=true|false`: each sector header describes the location of the
|
||||
sector: sector ID, track and side. Some formats use the wrong side ID, so
|
||||
the sectors on side 1 are labelled as belonging to side 0. This causes
|
||||
FluxEngine to see duplicate sectors (as it can't distinguish between the
|
||||
two sides). This option tells FluxEngine to ignore the side byte completely
|
||||
and use the physical side instead.
|
||||
|
||||
- `--ibm-required-sectors=range`: if you know how many sectors to expect per
|
||||
track, you can improve reads by telling FluxEngine what to expect here. If
|
||||
a track is read and a sector on this list is _not_ present, then FluxEngine
|
||||
assumes the read failed and will retry. This avoids the situation where
|
||||
FluxEngine can't tell the difference between a sector missing because it's
|
||||
bad or a sector missing because it was never written in the first place. If
|
||||
sectors are seen outside the range here, it will still be read. You can use
|
||||
the same syntax as for track specifiers: e.g. `0-9`, `0,1,2,3`, etc.
|
||||
|
||||
|
||||
Writing disks
|
||||
-------------
|
||||
|
||||
FluxEngine can also write IBM scheme disks. Unfortunately the format is
|
||||
incredibly flexible and you need to specify every single parameter, which
|
||||
makes things slightly awkward.
|
||||
|
||||
The syntax is:
|
||||
|
||||
fluxengine write ibm -i input.img <options>
|
||||
|
||||
The format of `input.img` will vary depending on the kind of disk you're
|
||||
writing, which is configured by the options. There are some presets, which
|
||||
you will almost certainly want to use if possible:
|
||||
|
||||
- `--ibm-preset-720`: a standard 720kB DS DD 3.5" disk, with 80 cylinders,
|
||||
2 sides, and 9 sectors per track.
|
||||
- `--ibm-preset-1440`: a standard 1440kB DS HD 3.5" disk, with 80
|
||||
cylinders, 2 sides, and 18 sectors per track.
|
||||
|
||||
These options simply preset the following, lower-level options. Note that
|
||||
options are processed left to right, so it's possible to use a preset and
|
||||
then change some settings. To see the values for a preset, simply append
|
||||
`--help`.
|
||||
|
||||
- `--ibm-track-length-ms=N`: one disk rotation, in milliseconds. This is used
|
||||
to determine whether all the data will fit on a track or not. `fluxengine
|
||||
rpm` will tell you this; it'll be 200 for a normal 3.5" drive and 166 for a
|
||||
normal 5.25" drive.
|
||||
- `--ibm-sector-size=N`: the size of a sector, in bytes. Must be a power of
|
||||
two.
|
||||
- `--ibm-emit-iam=true|false`: whether to emit the IAM record at the top of
|
||||
the track. The standard format requires it, but it's ignored by absolutely
|
||||
everyone and you can fit a bit more data on the disk without it.
|
||||
- `--ibm-start-sector-id=N`: the sector ID of the first sector. Normally 1,
|
||||
except for non-standard formats like Acorn's, which use 0.
|
||||
- `--ibm-use-fm=true|false`: uses FM rather than MFM.
|
||||
- `--ibm-idam-byte=N`: the sixteen-bit raw bit pattern used for the IDAM ID
|
||||
byte. Big-endian, clock bit first.
|
||||
- `--ibm-dam-byte-N`: the sixteen-bit raw bit pattern used for the DAM ID
|
||||
byte. Big-endian, clock bit first.
|
||||
- `--ibm-gap0-bytes=N`: the size of gap 0 in bytes (between the start of
|
||||
the track and the IAM record).
|
||||
- `--ibm-gap1-bytes=N`: the size of gap 1 in bytes (between the IAM record
|
||||
and the first sector record).
|
||||
- `--ibm-gap2-bytes=N`: the size of gap 2 in bytes (between each sector
|
||||
record and the data record).
|
||||
- `--ibm-gap3-bytes=N`: the size of gap 3 in bytes (between the data record
|
||||
and the next sector record).
|
||||
- `--ibm-sector-skew=0123...`: a string representing the order in which to
|
||||
write sectors: each character represents on sector, with `0` being the
|
||||
first (always, regardless of `--ibm-start-sector-id` above). Sectors 10 and
|
||||
above are represented as latters from `A` up.
|
||||
|
||||
Mixed-format disks
|
||||
------------------
|
||||
|
||||
Some disks, usually those belonging to early CP/M machines, have more than one
|
||||
format on the disk at once. Typically, the first few tracks will be low-density
|
||||
FM encoded and will be read by the machine's ROM; those tracks contain new
|
||||
floppy drive handling code capable of coping with MFM data, and so the rest of
|
||||
the disk will use that, allowing them to store more data.
|
||||
|
||||
FluxEngine copes with these fine, but the disk images are a bit weird. If track
|
||||
0 is FM and contains five sectors, but track 1 is MFM with nine sectors (MFM is
|
||||
more efficient and the sectors are physically smaller, allowing you to get more
|
||||
on), then the resulting image will have nine sectors per track... but track 0
|
||||
will only contain data in the first five.
|
||||
|
||||
This is typically what you want as it makes locating the sectors in the image
|
||||
easier, but emulators will typically require a different format. Please [get
|
||||
in touch](https://github.com/davidgiven/fluxengine/issues/new) if you have
|
||||
specific requirements (nothing's come up yet). Alternatively, you can tell
|
||||
FluxEngine to write a [`.ldbs`
|
||||
file](http://www.seasip.info/Unix/LibDsk/ldbs.html) and then use
|
||||
[libdsk](http://www.seasip.info/Unix/LibDsk/) to convert it to something
|
||||
useful.
|
||||
|
||||
One easy option when reading these is to simply read the two sections of the
|
||||
disk into two different image files.
|
||||
|
||||
FluxEngine can write these too, but in two different passes with different
|
||||
options. It's possible to assemble a flux file by judicious use of `-D
|
||||
something.flux --merge`, which can then be written in a single pass with
|
||||
`fluxengine writeflux`, but it's usually not worth the bother: just write the
|
||||
boot tracks, then write the data tracks, possibly with a script for automation.
|
||||
@@ -28,8 +28,16 @@ for example the Commodore 64 1541 drive, changed bitrate this way.
|
||||
But Macintosh disks used a constant bitrate and changed the speed that the
|
||||
disk spun instead to achieve the same effect...
|
||||
|
||||
_Anyway_: FluxEngine will read them fine on a conventional drive. Because
|
||||
it's clever.
|
||||
_Anyway_: FluxEngine will read them fine on conventional drives.
|
||||
Because it's clever.
|
||||
|
||||
**Big note.** Apparently --- and I'm still getting to the bottom of this ---
|
||||
some drives work and some don't. My drives produce about 90% good reads of
|
||||
known good disks. One rumour I've heard is that drives sometimes include
|
||||
filters which damage the signals at very particular intervals which Mac disks
|
||||
use, but frankly this seems unlikely; it could be a software issue at my end
|
||||
and I'm investigating. If you have any insight, please [get in
|
||||
touch](https://github.com/davidgiven/fluxengine/issues/new).
|
||||
|
||||
Reading discs
|
||||
-------------
|
||||
|
||||
20
doc/faq.md
20
doc/faq.md
@@ -48,7 +48,7 @@ haven't had the chance to try it end-for-end. I really need a hard-sectored
|
||||
|
||||
**Q.** Does it work with flippy disks?
|
||||
|
||||
Uhhh... probably not.
|
||||
Uhhh... maybe?
|
||||
|
||||
So the problem with flippy disks (5.25" single-sided disks which could be
|
||||
inserted upside down to read the second side) is the index hole. Trouble is,
|
||||
@@ -79,16 +79,26 @@ the other. But a flippy disk has both sets of tracks in the same place,
|
||||
because they're both accessed using the side 0 head...
|
||||
|
||||
The only real way round this is to modify a 5.25" drive. That's _seriously_
|
||||
not in FluxEngine's remit. Sorry.
|
||||
not in FluxEngine's remit, but I've had some [excellent documentation
|
||||
contributed](Index_sensor_mod_FDD_1.1.pdf) on how to do this. I've never done
|
||||
it myself; if you try this and it works/doesn't work, as always, [get in
|
||||
touch](https://github.com/davidgiven/fluxengine/issues/new).
|
||||
|
||||
**Q.** Is this like KryoFlux / Catweasel / DiskFerret? Do you support KryoFlux
|
||||
Another option is to fake the index signal to the drive completely. The
|
||||
FluxEngine emits suitable pulses for a 300RPM drive on pin 3[0] and the
|
||||
equivalent pulses for a 360RPM drive on pin 3[1]. Disclaimer: I have never used
|
||||
these.
|
||||
|
||||
**Q.** Is this like Supercard Pro / KryoFlux / Catweasel / DiskFerret? Do you
|
||||
*support KryoFlux
|
||||
stream files?
|
||||
|
||||
**A.** It's very like all of these; the idea's old, and lots of people have
|
||||
tried it (you can get away with any sufficiently fast microcontroller and
|
||||
enough RAM). FluxEngine can read from KryoFlux stream files natively, and
|
||||
there's a tool which will let you convert at least one kind of Catweasel file
|
||||
to FluxEngine's native flux file format.
|
||||
there's a tool which will let you convert at least one kind of Catweasel
|
||||
files and Supercard Pro files to and from FluxEngine's native flux file
|
||||
format.
|
||||
|
||||
**Q.** Can I use this to make exact copies of disks?
|
||||
|
||||
|
||||
@@ -59,53 +59,42 @@ Some useful and/or interesting numbers:
|
||||
|
||||
## Why don't I use an Arduino / STM32 / ESP32 / Raspberry Pi / etc?
|
||||
|
||||
I've got a _lot_ of questions on this, and multiple Github issues of people
|
||||
-I've got a _lot_ of questions on this, and multiple Github issues of people
|
||||
debating it. It's complicated, but it's essentially a tradeoff between speed
|
||||
and complexity.
|
||||
and complexity.-
|
||||
|
||||
FluxEngine's read process involves generating a lot of data using a fairly
|
||||
brute force sampling approach --- about 150kB per disk revolution, and
|
||||
sometimes it needs to record multiple revolutions. Most microcontrollers
|
||||
don't have enough RAM to buffer this, so instead I have to stream it over USB
|
||||
back to the host PC in real time. The disk won't wait, so I need to stream data faster
|
||||
than the disk is producing it: the total is about 800kB/s.
|
||||
**Update as of 2020-01-08:**
|
||||
|
||||
Handling USB is pretty CPU-hungry, so my candidate microntroller has to be
|
||||
able to cope with the ruinously strict real-time requirements of the
|
||||
sampler's 12MHz clock as well as keeping up with 13,000 USB interrupts a
|
||||
second (one for each 64-byte frame) in order to transfer the data.
|
||||
Right. Well.
|
||||
|
||||
The Atmels and STM32s I found were perfectly capable of doing the real-time
|
||||
sampling, using hand-tool assembly, but I very much doubt whether they could
|
||||
do the USB streaming as well (although I want to move away from the Cypress
|
||||
onto something less proprietary and easier to source, so I'd like to be
|
||||
proven wrong here).
|
||||
This section used to have a long explanation as to why these other platforms
|
||||
were unsuitable --- essentially, they're generally missing out on either the
|
||||
realtimeness to sample the data correctly (Raspberry Pi) or enough CPU to
|
||||
stream the data over USB while also sampling it (Arduino).
|
||||
|
||||
The Raspberry Pi easily has enough processing power and memory, but it's also
|
||||
got terrible GPIO pin read performance --- [about
|
||||
1kHz](https://raspberrypi.stackexchange.com/questions/9646/how-fast-is-gpiodma-multi-i2s-input/10197#10197).
|
||||
That's a long way from the 12MHz I need.
|
||||
This is correct, but it turns out that the STM32 has some built-in features
|
||||
which support the FluxEngine's use case almost exactly: you can configure the
|
||||
DMA engine to sample the interval between pulses and write them directly into
|
||||
memory, and you can configure the PWM engine the read samples from memory and
|
||||
use them to time pulses to the output. There's a bit less functionality, so you
|
||||
can't do things like measure the signal voltages, and they're less convenient
|
||||
as you need an adapter cable or board, but this will allow you to replicate the
|
||||
FluxEngine hardware on a $2 Blue Pill.
|
||||
|
||||
The PSoC5LP part I'm using has enough CPU to handle the USB side of things,
|
||||
and it _also_ has a whole set of FPGA-like soft programmable features,
|
||||
including 24 mini-ALU systems that are ideally suited to exactly this kind of
|
||||
sampling. I can read the disk and generate the byte stream describing the
|
||||
flux pattern entirely in 'hardware', without involving the main CPU at all.
|
||||
This is then DMAed directly into a set of ring buffers read for the USB
|
||||
system to pick up and relay back to the PC. It's incredibly simple and works
|
||||
well. (The same applies to writing flux back onto the disk.)
|
||||
I am _not_ planning on replacing the PSoC5 with a Blue Pill, because someone
|
||||
already has: [the GreaseWeazle](https://github.com/keirf/Greaseweazle/wiki) is
|
||||
a completely open source firmware package which will read and write Supercard
|
||||
Pro files via a standard Blue Pill. The GreaseWeazle's USB protocol is
|
||||
different from the FluxEngine's so they're not directly interchangeable. You
|
||||
can, however, read a Supercard Pro file with a GreaseWeazle and then use the
|
||||
FluxEngine client to decode it. It should work the other way around, too, but
|
||||
FluxEngine's SCP export [is curently
|
||||
broken](https://github.com/davidgiven/fluxengine/issues/134).
|
||||
|
||||
The development board I'm using, the
|
||||
[CY8CKIT-059](https://www.cypress.com/documentation/development-kitsboards/cy8ckit-059-psoc-5lp-prototyping-kit-onboard-programmer-and),
|
||||
also has another big advantage: it's the right shape. It's got 17 holes in a
|
||||
row connected to GPIO pins, and it's a native 5V part, which means I can just
|
||||
connect a floppy drive connector directly to the board without needing to
|
||||
build any hardware. No adapter board, no level shifting, no special cable,
|
||||
nothing. This makes the FluxEngine hardware incredibly easy to assemble,
|
||||
which therefore means cheap.
|
||||
I _am_ considering adding direct support for the GreaseWeazle to the FluxEngine
|
||||
client, which will let you just plug one in and make it go as a direct
|
||||
replacement to the FluxEngine hardware.
|
||||
|
||||
Speaking of which, the CY8CKIT-059 is $10. (Before shipping, which is
|
||||
admittedly expensive.)
|
||||
|
||||
### Some useful links
|
||||
|
||||
|
||||
218
doc/using.md
218
doc/using.md
@@ -1,68 +1,8 @@
|
||||
Using a FluxEngine
|
||||
==================
|
||||
|
||||
So you've [built the hardware](building.md)! What now?
|
||||
|
||||
## Connecting it up
|
||||
|
||||
In order to do anything useful, you have to plug it in to a floppy disk drive (or two).
|
||||
|
||||
1. Plug the motherboard end of your floppy disk cable into the FluxEngine.
|
||||
|
||||
The **red stripe goes on the right**. The **lower set of
|
||||
holes connect to the board**. (Pin 2 of the connector needs to connect
|
||||
to pin 2.7 on the board.)
|
||||
|
||||
If you're using header pins, the upper row of holes in the connector
|
||||
should overhang the edge of the board. If you're using a floppy drive
|
||||
motherboard connector, you're golden, of course (unless you have one of
|
||||
those annoying unkeyed cables, or have accidentally soldered the
|
||||
connector on in the wrong place --- don't laugh, I've done it.)
|
||||
|
||||
2. Plug the drive end of your floppy disk cable into the drive (or drives).
|
||||
|
||||
Floppy disk cables typically have [two pairs of floppy disk drive
|
||||
connectors with a twist between
|
||||
them](http://www.nullmodem.com/Floppy.htm). (Each pair has one connector
|
||||
for a 3.5" drive and a different one for a 5.25" drive.) (Some cables
|
||||
are cheap and just have the 3.5" connectors. Some are _very_ cheap and
|
||||
have a single 3.5" connector, after the twist.)
|
||||
|
||||
FluxEngine uses, sadly, non-standard disk numbering (there are reasons).
|
||||
Drive 0 is the one nearest the motherboard; that is, before the twist.
|
||||
Drive 1 is the one at the end of the cable; that is, after the twist.
|
||||
Drive 0 is the default. If you only have one drive, remember to plug the
|
||||
drive into the connector _before_ the twist. (Or use `-s :d=1` to select
|
||||
drive 1 when working with disks.)
|
||||
|
||||
3. **Important.** Make sure that no disk you care about is in the drive.
|
||||
(Because if your wiring is wrong and a disk is inserted, you'll corrupt it.)
|
||||
|
||||
4. Connect the floppy drive to power. Nothing should happen. If you've
|
||||
connected something in backwards, you'll see the drive light up, the
|
||||
motor start, and if you didn't take the disk out, one track has just
|
||||
been wiped. If this happens, check your wiring.
|
||||
|
||||
5. Connect the FluxEngine to your PC via USB --- using the little socket on
|
||||
the board, not the big programmer plug.
|
||||
|
||||
6. Insert a scratch disk and do `fluxengine rpm` from the shell. The motor
|
||||
should work and it'll tell you that the disk is spinning at about 300
|
||||
rpm for a 3.5" disk, or 360 rpm for a 5.25" disk. If it doesn't, please
|
||||
[get in touch](https://github.com/davidgiven/fluxengine/issues/new).
|
||||
|
||||
7. Do `fluxengine testbulktransport` from the shell. It'll measure your USB
|
||||
bandwidth. Ideally you should be getting above 900kB/s. FluxEngine needs
|
||||
about 850kB/s, so if you're getting less than this, try a different USB
|
||||
port.
|
||||
|
||||
8. Insert a standard PC formatted floppy disk into the drive (probably a good
|
||||
idea to remove the old disk first). Then do `fluxengine read ibm`. It
|
||||
should read the disk, emitting copious diagnostics, and spit out an
|
||||
`ibm.img` file containing the decoded disk image (either 1440kB or 720kB
|
||||
depending).
|
||||
|
||||
9. Profit!
|
||||
So you've [built the hardware](building.md), programmed and tested it! What
|
||||
now?
|
||||
|
||||
## The programs
|
||||
|
||||
@@ -71,10 +11,33 @@ moving too quickly for the documentation to keep up. It does respond to
|
||||
`--help` or `help` depending on context. There are some common properties,
|
||||
described below.
|
||||
|
||||
### Core concepts
|
||||
|
||||
FluxEngine fundamentally takes file system images and puts them on disk; or
|
||||
reads the disk and produces a file system image.
|
||||
|
||||
A file system image typically has the extension `.img`. It contains a
|
||||
sector-by-sector record of the _decoded_ data on the disk. For example, on a
|
||||
disk with 512 byte sectors, one sector will occupy 512 bytes. These are
|
||||
typically what you want in everyday life.
|
||||
|
||||
FluxEngine can also record the raw magnetic data on the disk into a file, which
|
||||
we call a _flux file_. This contains all the low-level data which the drive
|
||||
produced as the disk rotated. These are continuous streams of samples from the
|
||||
disk and are completely useless in day-to-day life. FluxEngine uses its own
|
||||
format for this, `.flux`, although it's capable of limited interchange with
|
||||
Kryoflux, Supercard Pro and Catweasel files. A flux file will typically contain
|
||||
from 80 to 150 kilobytes of data per track.
|
||||
|
||||
In general, FluxEngine can use either a real disk or a flux file
|
||||
interchangeably: you can specify either at (very nearly) any time. A very
|
||||
common workflow is to read a disk to a flux file, and then reread from the flux
|
||||
file while changing the decoder options, to save disk wear. It's also much faster.
|
||||
|
||||
### Source and destination specifiers
|
||||
|
||||
When reading from or writing to _a disk_ (or a file pretending to be a disk),
|
||||
use the `--source` (`-s`) and `--dest` (`-d`) options to tell FluxEngine
|
||||
When reading from or writing _flux_ (either from or to a real disk, or a flux
|
||||
file), use the `--source` (`-s`) and `--dest` (`-d`) options to tell FluxEngine
|
||||
which bits of the disk you want to access. These use a common syntax:
|
||||
|
||||
```
|
||||
@@ -84,7 +47,7 @@ fluxengine read ibm -s fakedisk.flux:t=0-79:s=0
|
||||
- To access a real disk, leave out the filename (so `:t=0-79:s=0`).
|
||||
|
||||
- To access only some tracks, use the `t=` modifier. To access only some
|
||||
sides, use the `s=` modifier. To change drives, use `d=`.
|
||||
sides, use the `s=` modifier.
|
||||
|
||||
- Inside a modifier, you can use a comma separated list of ranges. So
|
||||
`:t=0-3` and `:t=0,1,2,3` are equivalent.
|
||||
@@ -110,18 +73,15 @@ If you _don't_ specify a modifier, you'll get the default, which should be
|
||||
sensible for the command you're using.
|
||||
|
||||
**Important note:** FluxEngine _always_ uses zero-based units (even if the
|
||||
*disk format says otherwise).
|
||||
disk format says otherwise).
|
||||
|
||||
### Input and output specifiers
|
||||
|
||||
These use a very similar syntax to the source and destination specifiers
|
||||
(because they're based on the same microformat library!) but are used for
|
||||
input and output _images_: i.e. nicely lined up arrays of sectors which you
|
||||
can actually do something with.
|
||||
|
||||
Use `--input` (`-i`) or `--output` (`-o`) as appropriate to tell FluxEngine
|
||||
where you want to read from or write to. The actual format is autodetected
|
||||
based on the extension:
|
||||
When reading or writing _file system images_, use the `--input` (`-i`) and
|
||||
`--output` (`-o`) options to specify the file and file format. These use a very
|
||||
similar syntax to the source and destination specifiers (because they're based
|
||||
on the same microformat library!) but with different specifiers. Also, the
|
||||
exact format varies according to the extension:
|
||||
|
||||
- `.img` or `.adf`: raw sector images in CHS order. Append
|
||||
`:c=80:h=2:s=9:b=512` to set the geometry; that specifies 80 cylinders, 2
|
||||
@@ -176,6 +136,29 @@ case, and reading the disk label is much more reliable.
|
||||
[Lots more information on high density vs double density disks can be found
|
||||
here.](http://www.retrotechnology.com/herbs_stuff/guzis.html)
|
||||
|
||||
### Other important flags
|
||||
|
||||
These flags apply to many operations and are useful for modifying the overall
|
||||
behaviour.
|
||||
|
||||
- `--revolutions=X`: when reading, spin the disk X times. X can be a floating
|
||||
point number. The default is usually 1.25. Some formats default to 1.
|
||||
Increasing the number will sample more data, and can be useful on dubious
|
||||
disks to try and get a better read.
|
||||
|
||||
- `--sync-with-index=true|false`: wait for an index pulse before starting to
|
||||
read the disk. (Ignored for write operations.) By default FluxEngine
|
||||
doesn't, as it makes reads faster, but when diagnosing disk problems it's
|
||||
helpful to have all your data start at the same place each time.
|
||||
|
||||
- `--index-source=X`, `--write-index-source=X`: set the source of index
|
||||
pulses when reading or writing respectively. This is for use with drives
|
||||
which don't produce index pulse data. Use 0 to get index pulses from the
|
||||
drive, 1 to fake 300RPM pulses, or 2 to fake 360RPM pulses. Note this has
|
||||
no effect on the _drive_, so it doesn't help with flippy disks, but is
|
||||
useful for using very old drives with FluxEngine itself. If you use this
|
||||
option, then any index marks in the sampled flux are, of course, garbage.
|
||||
|
||||
### The commands
|
||||
|
||||
The FluxEngine client software is a largely undocumented set of small tools.
|
||||
@@ -184,56 +167,61 @@ installed anywhere and after building you'll find them in the `.obj`
|
||||
directory.
|
||||
|
||||
- `fluxengine erase`: wipes (all or part of) a disk --- erases it without
|
||||
writing a pulsetrain.
|
||||
writing a pulsetrain.
|
||||
|
||||
- `fluxengine inspect`: dumps the raw pulsetrain / bitstream to stdout.
|
||||
Mainly useful for debugging.
|
||||
Mainly useful for debugging.
|
||||
|
||||
- `fluxengine read*`: reads various formats of disk. See the per-format
|
||||
documentation linked from the table above. These all take an optional
|
||||
`--write-flux` option which will cause the raw flux to be written to the
|
||||
specified file.
|
||||
- `fluxengine read *`: reads various formats of disk. See the per-format
|
||||
documentation linked from the table [in the index page](../README.md).
|
||||
These all take an optional `--write-flux` option which will cause the raw
|
||||
flux to be written to the specified file as well as the normal decode.
|
||||
There are various `--dump` options for showing raw data during the decode
|
||||
process.
|
||||
|
||||
- `fluxengine write*`: writes various formats of disk. Again, see the
|
||||
per-format documentation above.
|
||||
- `fluxengine write *`: writes various formats of disk. Again, see the
|
||||
per-format documentation [in the index page](../README.md).
|
||||
|
||||
- `fluxengine writeflux`: writes raw flux files. This is much less useful
|
||||
than you might think: you can't write flux files read from a disk to
|
||||
another disk. (See the [FAQ](faq.md) for more information.) It's mainly
|
||||
useful for flux files synthesised by the other `fluxengine write` commands.
|
||||
than you might think: you can't reliably write flux files read from a disk
|
||||
to another disk. (See the [FAQ](faq.md) for more information.) It's mainly
|
||||
useful for flux files synthesised by the other `fluxengine write` commands.
|
||||
|
||||
- `fluxengine writetestpattern`: writes regular pulses (at a configurable
|
||||
interval) to the disk. Useful for testing drive jitter, erasing disks in a
|
||||
more secure fashion, or simply debugging. Goes well with `fluxengine
|
||||
inspect`.
|
||||
interval) to the disk. Useful for testing drive jitter, erasing disks in a
|
||||
more secure fashion, or simply debugging. Goes well with `fluxengine
|
||||
inspect`.
|
||||
|
||||
- `fluxengine rpm`: measures the RPM of the drive (requires a disk in the
|
||||
drive). Mainly useful for testing.
|
||||
drive). Mainly useful for testing.
|
||||
|
||||
- `fluxengine seek`: moves the head. Mainly useful for finding out whether
|
||||
your drive can seek to track 82. (Mine can't.)
|
||||
your drive can seek to track 82. (Mine can't.)
|
||||
|
||||
- `fluxengine testbulktransport`: measures your USB throughput. You need
|
||||
about 600kB/s for FluxEngine to work. You don't need a disk in the drive
|
||||
for this one.
|
||||
- `fluxengine test bandwidth`: measures your USB throughput. You don't need
|
||||
a disk in the drive for this one.
|
||||
|
||||
- `fluxengine upgradefluxfile`: occasionally I need to upgrade the flux
|
||||
file format in a non-backwards-compatible way; this tool will upgrade flux
|
||||
files to the new format.
|
||||
- `fluxengine test voltages`: measures your FDD bus signal voltages, which is
|
||||
useful for testing for termination issues.
|
||||
|
||||
- `fluxengine upgradefluxfile`: occasionally I need to upgrade the flux file
|
||||
format in a non-backwards-compatible way; this tool will upgrade flux files
|
||||
to the new format.
|
||||
|
||||
- `fluxengine convert`: converts flux files from various formats to various
|
||||
other formats. You can use this to convert Catweasel flux files to
|
||||
FluxEngine's native format, FluxEngine flux files to various other formats
|
||||
useful for debugging (including VCD which can be loaded into
|
||||
[sigrok](http://sigrok.org)), and bidirectional conversion to and from
|
||||
Supercard Pro `.scp` format.
|
||||
other formats. You can use this to convert Catweasel flux files to
|
||||
FluxEngine's native format, FluxEngine flux files to various other formats
|
||||
useful for debugging (including VCD which can be loaded into
|
||||
[sigrok](http://sigrok.org)), and bidirectional conversion to and from
|
||||
Supercard Pro `.scp` format.
|
||||
|
||||
**Important SCP note:** import (`fluxengine convert scptoflux`) should be
|
||||
fairly robust, but export (`fluxengine convert fluxtoscp`) should only be
|
||||
done with great caution as FluxEngine files contain features which can't be
|
||||
represented very well in `.scp` format and they're probably pretty dubious.
|
||||
As ever, please [get in
|
||||
touch](https://github.com/davidgiven/fluxengine/issues/new) with any reports.
|
||||
**Important SCP note:** import (`fluxengine convert scptoflux`) should be
|
||||
fairly robust, but export (`fluxengine convert fluxtoscp`) should only be
|
||||
done with great caution as FluxEngine files contain features which can't be
|
||||
represented very well in `.scp` format and they're probably pretty dubious.
|
||||
As ever, please [get in
|
||||
touch](https://github.com/davidgiven/fluxengine/issues/new) with any
|
||||
reports.
|
||||
|
||||
Commands which normally take `--source` or `--dest` get a sensible default if
|
||||
left unspecified. `fluxengine read ibm` on its own will read drive 0 and
|
||||
@@ -259,8 +247,10 @@ disk). For a 5.25" disk, use `--visualiser-period=166`.
|
||||
Supplied with FluxEngine, but not part of FluxEngine, are some little tools I
|
||||
wrote to do useful things. These are built alongside FluxEngine.
|
||||
|
||||
- `brother120tool`: extracts files from a 120kB Brother filesystem image.
|
||||
|
||||
- `brother120tool`, `brother240tool`: does things to Brother word processor
|
||||
disks. These are [documented on the Brother disk format
|
||||
page](disk-brother.md).
|
||||
|
||||
## The recommended workflow
|
||||
|
||||
So you've just received, say, a huge pile of old Brother word processor disks
|
||||
@@ -269,13 +259,13 @@ containing valuable historical data, and you want to read them.
|
||||
Typically I do this:
|
||||
|
||||
```
|
||||
$ fluxengine read brother -s :d=0 -o brother.img --write-flux=brother.flux --write-svg=brother.svg
|
||||
$ fluxengine read brother -s :d=0 -o brother.img --write-flux=brother.flux --overwrite --write-svg=brother.svg
|
||||
```
|
||||
|
||||
This will read the disk in drive 0 and write out a filesystem image. It'll
|
||||
also copy the flux to brother.flux and write out an SVG visualisation. If I
|
||||
then need to tweak the settings, I can rerun the decode without having to
|
||||
physically touch the disk like this:
|
||||
This will read the disk in drive 0 and write out a filesystem image. It'll also
|
||||
copy the flux to `brother.flux` (replacing any old one) and write out an SVG
|
||||
visualisation. If I then need to tweak the settings, I can rerun the decode
|
||||
without having to physically touch the disk like this:
|
||||
|
||||
```
|
||||
$ fluxengine read brother -s brother.flux -o brother.img --write-svg=brother.svg
|
||||
|
||||
22
lib/bytes.cc
22
lib/bytes.cc
@@ -147,6 +147,28 @@ Bytes Bytes::slice(unsigned start, unsigned len) const
|
||||
}
|
||||
}
|
||||
|
||||
Bytes Bytes::slice(unsigned start) const
|
||||
{
|
||||
int len = 0;
|
||||
if (start < size())
|
||||
len = size() - start;
|
||||
return slice(start, len);
|
||||
}
|
||||
|
||||
std::vector<bool> Bytes::toBits() const
|
||||
{
|
||||
std::vector<bool> bits;
|
||||
for (uint8_t byte : *this)
|
||||
{
|
||||
for (int i=0; i<8; i++)
|
||||
{
|
||||
bits.push_back(byte & 0x80);
|
||||
byte <<= 1;
|
||||
}
|
||||
}
|
||||
return bits;
|
||||
}
|
||||
|
||||
uint8_t toByte(
|
||||
std::vector<bool>::const_iterator start,
|
||||
std::vector<bool>::const_iterator end)
|
||||
|
||||
@@ -47,11 +47,13 @@ public:
|
||||
{ resize(0); return *this; }
|
||||
|
||||
Bytes slice(unsigned start, unsigned len) const;
|
||||
Bytes slice(unsigned start) const;
|
||||
Bytes swab() const;
|
||||
Bytes compress() const;
|
||||
Bytes decompress() const;
|
||||
Bytes crunch() const;
|
||||
Bytes uncrunch() const;
|
||||
std::vector<bool> toBits() const;
|
||||
|
||||
ByteReader reader() const;
|
||||
ByteWriter writer();
|
||||
|
||||
@@ -9,14 +9,37 @@ void crunch(crunch_state_t* state)
|
||||
uint8_t data = *state->inputptr++;
|
||||
state->inputlen--;
|
||||
|
||||
if (data & 0x80)
|
||||
if (data == 0x80)
|
||||
{
|
||||
/* Multiple 0x80s in a row get swallowed as they're
|
||||
* meaningless. */
|
||||
state->haspending = true;
|
||||
}
|
||||
else if (data & 0x80)
|
||||
{
|
||||
state->fifo = (state->fifo << 2) | 2 | (data & 1);
|
||||
state->fifolen += 2;
|
||||
if (state->haspending)
|
||||
{
|
||||
state->fifo = (state->fifo << 3) | 4;
|
||||
state->fifolen += 3;
|
||||
state->haspending = false;
|
||||
}
|
||||
|
||||
state->fifo = (state->fifo << 3) | 4 | (data & 1);
|
||||
state->fifolen += 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
state->fifo = (state->fifo << 8) | data;
|
||||
if (state->haspending && (data >= 0x40))
|
||||
{
|
||||
state->fifo = (state->fifo << 3) | 4;
|
||||
state->fifolen += 3;
|
||||
state->haspending = false;
|
||||
}
|
||||
|
||||
state->fifo = (state->fifo << 8) | data;
|
||||
if (state->haspending)
|
||||
state->fifo |= 0xc0;
|
||||
state->haspending = false;
|
||||
state->fifolen += 8;
|
||||
}
|
||||
|
||||
@@ -45,6 +68,14 @@ void uncrunch(crunch_state_t* state)
|
||||
{
|
||||
while (state->inputlen && state->outputlen)
|
||||
{
|
||||
if (state->haspending)
|
||||
{
|
||||
*state->outputptr++ = state->pendingbyte;
|
||||
state->outputlen--;
|
||||
state->haspending = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (state->fifolen < 8)
|
||||
{
|
||||
if (state->inputlen)
|
||||
@@ -58,13 +89,21 @@ void uncrunch(crunch_state_t* state)
|
||||
}
|
||||
|
||||
uint8_t data = state->fifo >> (state->fifolen - 8);
|
||||
if (data & 0x80)
|
||||
{
|
||||
data = ((data >> 6) & 0x01) | 0x80;
|
||||
state->fifolen -= 2;
|
||||
}
|
||||
else
|
||||
state->fifolen -= 8;
|
||||
switch (data & 0xc0)
|
||||
{
|
||||
case 0x80:
|
||||
data = ((data >> 5) & 0x01) | 0x80;
|
||||
state->fifolen -= 3;
|
||||
break;
|
||||
|
||||
case 0xc0:
|
||||
state->haspending = true;
|
||||
state->pendingbyte = data & 0x3f;
|
||||
data = 0x80;
|
||||
/* fall through */
|
||||
default:
|
||||
state->fifolen -= 8;
|
||||
}
|
||||
|
||||
if (data)
|
||||
{
|
||||
|
||||
@@ -11,7 +11,8 @@ extern "C" {
|
||||
* sending it over USB. The encoding used is:
|
||||
*
|
||||
* 0nnn.nnnn: value 0x00..0x7f
|
||||
* 1n : value 0x80|n
|
||||
* 11nn.nnnn: value 0x80 then 0x00..0x3f
|
||||
* 10n : value 0x80|n
|
||||
*
|
||||
* The end of the buffer is terminated with zeroes, which are ignored
|
||||
* (not written to the output).
|
||||
@@ -25,8 +26,10 @@ typedef struct crunch_state_t
|
||||
uint32_t inputlen;
|
||||
uint8_t* outputptr;
|
||||
uint32_t outputlen;
|
||||
uint16_t fifo;
|
||||
uint32_t fifo;
|
||||
uint8_t fifolen;
|
||||
bool haspending;
|
||||
uint8_t pendingbyte;
|
||||
}
|
||||
crunch_state_t;
|
||||
|
||||
|
||||
@@ -15,34 +15,31 @@ std::vector<std::string> DataSpec::split(
|
||||
{
|
||||
std::vector<std::string> ret;
|
||||
|
||||
size_t start = 0;
|
||||
size_t end = 0;
|
||||
size_t len = 0;
|
||||
do
|
||||
{
|
||||
end = s.find(delimiter,start);
|
||||
len = end - start;
|
||||
std::string token = s.substr(start, len);
|
||||
ret.emplace_back( token );
|
||||
start += len + delimiter.length();
|
||||
}
|
||||
while (end != std::string::npos);
|
||||
if (!s.empty())
|
||||
{
|
||||
size_t start = 0;
|
||||
size_t end = 0;
|
||||
size_t len = 0;
|
||||
do
|
||||
{
|
||||
end = s.find(delimiter,start);
|
||||
len = end - start;
|
||||
std::string token = s.substr(start, len);
|
||||
ret.emplace_back( token );
|
||||
start += len + delimiter.length();
|
||||
}
|
||||
while (end != std::string::npos);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
DataSpec::Modifier DataSpec::parseMod(const std::string& spec)
|
||||
std::set<unsigned> DataSpec::parseRange(const std::string& data)
|
||||
{
|
||||
static const std::regex MOD_REGEX("([a-z]*)=([-x+0-9,]*)");
|
||||
static const std::regex DATA_REGEX("([0-9]+)(?:(?:-([0-9]+))|(?:\\+([0-9]+)))?(?:x([0-9]+))?");
|
||||
static const std::regex DATA_REGEX("([0-9]+)(?:(?:-([0-9]+))|(?:\\+([0-9]+)))?(?:x([0-9]+))?");
|
||||
|
||||
std::smatch match;
|
||||
if (!std::regex_match(spec, match, MOD_REGEX))
|
||||
Error() << "invalid data modifier syntax '" << spec << "'";
|
||||
|
||||
Modifier m;
|
||||
m.name = match[1];
|
||||
m.source = spec;
|
||||
for (auto& data : split(match[2], ","))
|
||||
std::set<unsigned> result;
|
||||
for (auto& data : split(data, ","))
|
||||
{
|
||||
int start = 0;
|
||||
int count = 1;
|
||||
@@ -64,9 +61,24 @@ DataSpec::Modifier DataSpec::parseMod(const std::string& spec)
|
||||
Error() << "mod '" << data << "' specifies an illegal quantity";
|
||||
|
||||
for (int i = start; i < (start+count); i += step)
|
||||
m.data.insert(i);
|
||||
result.insert(i);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
DataSpec::Modifier DataSpec::parseMod(const std::string& spec)
|
||||
{
|
||||
static const std::regex MOD_REGEX("([a-z]*)=([-x+0-9,]*)");
|
||||
|
||||
std::smatch match;
|
||||
if (!std::regex_match(spec, match, MOD_REGEX))
|
||||
Error() << "invalid data modifier syntax '" << spec << "'";
|
||||
|
||||
Modifier m;
|
||||
m.name = match[1];
|
||||
m.source = spec;
|
||||
m.data = parseRange(match[2]);
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -74,7 +86,7 @@ void DataSpec::set(const std::string& spec)
|
||||
{
|
||||
std::vector<std::string> words = split(spec, ":");
|
||||
if (words.size() == 0)
|
||||
Error() << "empty data specification (you have to specify *something*)";
|
||||
return;
|
||||
|
||||
filename = words[0];
|
||||
if (words.size() > 1)
|
||||
|
||||
@@ -34,6 +34,8 @@ public:
|
||||
public:
|
||||
static std::vector<std::string> split(
|
||||
const std::string& s, const std::string& delimiter);
|
||||
static std::set<unsigned> parseRange(const std::string& spec);
|
||||
|
||||
static Modifier parseMod(const std::string& spec);
|
||||
|
||||
public:
|
||||
@@ -117,4 +119,34 @@ private:
|
||||
DataSpec _value;
|
||||
};
|
||||
|
||||
class RangeFlag : public Flag
|
||||
{
|
||||
public:
|
||||
RangeFlag(const std::vector<std::string>& names, const std::string helptext,
|
||||
const std::string& defaultValue):
|
||||
Flag(names, helptext),
|
||||
_stringValue(defaultValue),
|
||||
_value(DataSpec::parseRange(defaultValue))
|
||||
{}
|
||||
|
||||
const std::set<unsigned>& get() const
|
||||
{ checkInitialised(); return _value; }
|
||||
|
||||
operator const std::set<unsigned>& () const
|
||||
{ return get(); }
|
||||
|
||||
bool hasArgument() const { return true; }
|
||||
const std::string defaultValueAsString() const { return _stringValue; }
|
||||
|
||||
void set(const std::string& value)
|
||||
{
|
||||
_stringValue = value;
|
||||
_value = DataSpec::parseRange(value);
|
||||
}
|
||||
|
||||
private:
|
||||
std::string _stringValue;
|
||||
std::set<unsigned> _value;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -25,7 +25,7 @@ void AbstractDecoder::decodeToSectors(Track& track)
|
||||
beginTrack();
|
||||
for (;;)
|
||||
{
|
||||
Fluxmap::Position recordStart = sector.position = fmr.tell();
|
||||
Fluxmap::Position recordStart = fmr.tell();
|
||||
sector.clock = 0;
|
||||
sector.status = Sector::MISSING;
|
||||
sector.data.clear();
|
||||
@@ -41,7 +41,7 @@ void AbstractDecoder::decodeToSectors(Track& track)
|
||||
|
||||
/* Read the sector record. */
|
||||
|
||||
recordStart = fmr.tell();
|
||||
sector.position = recordStart = fmr.tell();
|
||||
decodeSectorRecord();
|
||||
Fluxmap::Position recordEnd = fmr.tell();
|
||||
pushRecord(recordStart, recordEnd);
|
||||
@@ -51,14 +51,19 @@ void AbstractDecoder::decodeToSectors(Track& track)
|
||||
|
||||
sector.headerStartTime = recordStart.ns();
|
||||
sector.headerEndTime = recordEnd.ns();
|
||||
r = advanceToNextRecord();
|
||||
for (;;)
|
||||
{
|
||||
r = advanceToNextRecord();
|
||||
if (r != UNKNOWN_RECORD)
|
||||
break;
|
||||
if (fmr.readNextMatchingOpcode(F_OP_PULSE) == 0)
|
||||
break;
|
||||
}
|
||||
recordStart = fmr.tell();
|
||||
if (r == DATA_RECORD)
|
||||
{
|
||||
recordStart = fmr.tell();
|
||||
decodeDataRecord();
|
||||
recordEnd = fmr.tell();
|
||||
pushRecord(recordStart, recordEnd);
|
||||
}
|
||||
recordEnd = fmr.tell();
|
||||
pushRecord(recordStart, recordEnd);
|
||||
}
|
||||
sector.dataStartTime = recordStart.ns();
|
||||
sector.dataEndTime = recordEnd.ns();
|
||||
@@ -83,3 +88,10 @@ void AbstractDecoder::pushRecord(const Fluxmap::Position& start, const Fluxmap::
|
||||
_track->rawrecords.push_back(record);
|
||||
_fmr->seek(here);
|
||||
}
|
||||
|
||||
std::set<unsigned> AbstractDecoder::requiredSectors(Track& track) const
|
||||
{
|
||||
static std::set<unsigned> empty;
|
||||
return empty;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,8 @@ extern void setDecoderManualClockRate(double clockrate_us);
|
||||
|
||||
extern Bytes decodeFmMfm(std::vector<bool>::const_iterator start,
|
||||
std::vector<bool>::const_iterator end);
|
||||
extern void encodeMfm(std::vector<bool>& bits, unsigned& cursor, const Bytes& input, bool& lastBit);
|
||||
extern void encodeFm(std::vector<bool>& bits, unsigned& cursor, const Bytes& input);
|
||||
|
||||
static inline Bytes decodeFmMfm(const std::vector<bool> bits)
|
||||
{ return decodeFmMfm(bits.begin(), bits.end()); }
|
||||
@@ -50,6 +52,11 @@ public:
|
||||
void seek(const Fluxmap::Position& pos)
|
||||
{ return _fmr->seek(pos); }
|
||||
|
||||
/* Returns a set of sectors required to exist on this track. If the reader
|
||||
* sees any missing, it will consider this to be an error and will retry
|
||||
* the read. */
|
||||
virtual std::set<unsigned> requiredSectors(Track& track) const;
|
||||
|
||||
protected:
|
||||
virtual void beginTrack() {};
|
||||
virtual RecordType advanceToNextRecord() = 0;
|
||||
|
||||
@@ -18,13 +18,18 @@ DoubleFlag pulseDebounceThreshold(
|
||||
static DoubleFlag clockDecodeThreshold(
|
||||
{ "--bit-error-threshold" },
|
||||
"Amount of error to tolerate in pulse timing, in fractions of a clock.",
|
||||
0.20);
|
||||
0.40);
|
||||
|
||||
static DoubleFlag clockIntervalBias(
|
||||
{ "--clock-interval-bias" },
|
||||
"Adjust intervals between pulses by this many clocks before decoding.",
|
||||
-0.02);
|
||||
|
||||
static DoubleFlag minimumClockUs(
|
||||
{ "--minimum-clock-us" },
|
||||
"Refuse to detect clocks shorter than this, to avoid false positives.",
|
||||
0.75);
|
||||
|
||||
int FluxmapReader::readOpcode(unsigned& ticks)
|
||||
{
|
||||
ticks = 0;
|
||||
@@ -222,7 +227,9 @@ nanoseconds_t FluxmapReader::seekToPattern(const FluxMatcher& pattern, const Flu
|
||||
seek(positions[intervalCount-match.intervals]);
|
||||
_pos.zeroes = match.zeroes;
|
||||
matching = match.matcher;
|
||||
return match.clock * NS_PER_TICK;
|
||||
nanoseconds_t detectedClock = match.clock * NS_PER_TICK;
|
||||
if (detectedClock > (minimumClockUs*1000))
|
||||
return match.clock * NS_PER_TICK;
|
||||
}
|
||||
|
||||
for (unsigned i=0; i<intervalCount; i++)
|
||||
|
||||
@@ -51,3 +51,48 @@ Bytes decodeFmMfm(
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
void encodeFm(std::vector<bool>& bits, unsigned& cursor, const Bytes& input)
|
||||
{
|
||||
if (bits.size() == 0)
|
||||
return;
|
||||
unsigned len = bits.size()-1;
|
||||
|
||||
for (uint8_t b : input)
|
||||
{
|
||||
for (int i=0; i<8; i++)
|
||||
{
|
||||
bool bit = b & 0x80;
|
||||
b <<= 1;
|
||||
|
||||
if (cursor >= len)
|
||||
return;
|
||||
|
||||
bits[cursor++] = true;
|
||||
bits[cursor++] = bit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void encodeMfm(std::vector<bool>& bits, unsigned& cursor, const Bytes& input, bool& lastBit)
|
||||
{
|
||||
if (bits.size() == 0)
|
||||
return;
|
||||
unsigned len = bits.size()-1;
|
||||
|
||||
for (uint8_t b : input)
|
||||
{
|
||||
for (int i=0; i<8; i++)
|
||||
{
|
||||
bool bit = b & 0x80;
|
||||
b <<= 1;
|
||||
|
||||
if (cursor >= len)
|
||||
return;
|
||||
|
||||
bits[cursor++] = !lastBit && !bit;
|
||||
bits[cursor++] = bit;
|
||||
lastBit = bit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "globals.h"
|
||||
#include "flags.h"
|
||||
#include "fmt/format.h"
|
||||
|
||||
static FlagGroup* currentFlagGroup;
|
||||
static std::vector<Flag*> all_flags;
|
||||
@@ -157,6 +158,8 @@ Flag::Flag(const std::vector<std::string>& names, const std::string helptext):
|
||||
_names(names),
|
||||
_helptext(helptext)
|
||||
{
|
||||
if (!currentFlagGroup)
|
||||
Error() << "no flag group defined for " << *names.begin();
|
||||
_group.addFlag(this);
|
||||
}
|
||||
|
||||
@@ -170,6 +173,11 @@ void BoolFlag::set(const std::string& value)
|
||||
Error() << "can't parse '" << value << "'; try 'true' or 'false'";
|
||||
}
|
||||
|
||||
const std::string HexIntFlag::defaultValueAsString() const
|
||||
{
|
||||
return fmt::format("0x{:x}", _defaultValue);
|
||||
}
|
||||
|
||||
static void doHelp()
|
||||
{
|
||||
std::cout << "FluxEngine options:" << std::endl;
|
||||
|
||||
13
lib/flags.h
13
lib/flags.h
@@ -135,6 +135,17 @@ public:
|
||||
void set(const std::string& value) { _value = std::stoi(value); }
|
||||
};
|
||||
|
||||
class HexIntFlag : public IntFlag
|
||||
{
|
||||
public:
|
||||
HexIntFlag(const std::vector<std::string>& names, const std::string helptext,
|
||||
int defaultValue = 0):
|
||||
IntFlag(names, helptext, defaultValue)
|
||||
{}
|
||||
|
||||
const std::string defaultValueAsString() const;
|
||||
};
|
||||
|
||||
class DoubleFlag : public ValueFlag<double>
|
||||
{
|
||||
public:
|
||||
@@ -147,7 +158,7 @@ public:
|
||||
void set(const std::string& value) { _value = std::stod(value); }
|
||||
};
|
||||
|
||||
class BoolFlag : public ValueFlag<double>
|
||||
class BoolFlag : public ValueFlag<bool>
|
||||
{
|
||||
public:
|
||||
BoolFlag(const std::vector<std::string>& names, const std::string helptext,
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
#ifndef FLUXSINK_H
|
||||
#define FLUXSINK_H
|
||||
|
||||
#include "flags.h"
|
||||
|
||||
extern FlagGroup hardwareFluxSinkFlags;
|
||||
extern FlagGroup sqliteFluxSinkFlags;
|
||||
|
||||
class Fluxmap;
|
||||
class FluxSpec;
|
||||
|
||||
@@ -9,11 +14,9 @@ class FluxSink
|
||||
public:
|
||||
virtual ~FluxSink() {}
|
||||
|
||||
private:
|
||||
static std::unique_ptr<FluxSink> createSqliteFluxSink(const std::string& filename);
|
||||
static std::unique_ptr<FluxSink> createHardwareFluxSink(unsigned drive);
|
||||
|
||||
public:
|
||||
static std::unique_ptr<FluxSink> create(const FluxSpec& spec);
|
||||
|
||||
public:
|
||||
|
||||
@@ -4,8 +4,15 @@
|
||||
#include "usb.h"
|
||||
#include "fluxsink/fluxsink.h"
|
||||
|
||||
FlagGroup hardwareFluxSinkFlags;
|
||||
|
||||
static bool high_density = false;
|
||||
|
||||
static IntFlag indexMode(
|
||||
{ "--write-index-mode" },
|
||||
"index pulse source (0=drive, 1=300 RPM fake source, 2=360 RPM fake source",
|
||||
0);
|
||||
|
||||
void setHardwareFluxSinkDensity(bool high_density)
|
||||
{
|
||||
::high_density = high_density;
|
||||
@@ -26,7 +33,7 @@ public:
|
||||
public:
|
||||
void writeFlux(int track, int side, Fluxmap& fluxmap)
|
||||
{
|
||||
usbSetDrive(_drive, high_density);
|
||||
usbSetDrive(_drive, high_density, indexMode);
|
||||
usbSeek(track);
|
||||
|
||||
Bytes crunched = fluxmap.rawBytes().crunch();
|
||||
|
||||
@@ -2,14 +2,37 @@
|
||||
#include "fluxmap.h"
|
||||
#include "sql.h"
|
||||
#include "fluxsink/fluxsink.h"
|
||||
#include "flags.h"
|
||||
#include "fmt/format.h"
|
||||
#include <unistd.h>
|
||||
|
||||
FlagGroup sqliteFluxSinkFlags;
|
||||
|
||||
static SettableFlag mergeFlag(
|
||||
{ "--merge" },
|
||||
"merge new data into existing flux file");
|
||||
|
||||
static SettableFlag overwriteFlag(
|
||||
{ "--overwrite" },
|
||||
"overwrite existing flux file");
|
||||
|
||||
class SqliteFluxSink : public FluxSink
|
||||
{
|
||||
public:
|
||||
SqliteFluxSink(const std::string& filename)
|
||||
{
|
||||
if (mergeFlag && overwriteFlag)
|
||||
Error() << "you can't specify --merge and --overwrite";
|
||||
|
||||
if (!mergeFlag)
|
||||
{
|
||||
if (!overwriteFlag && (access(filename.c_str(), F_OK) == 0))
|
||||
Error() << "cowardly refusing to overwrite flux file without --merge or --overwrite specified";
|
||||
if ((access(filename.c_str(), F_OK) == 0) && (remove(filename.c_str()) != 0))
|
||||
Error() << fmt::format("failed to overwrite flux file");
|
||||
}
|
||||
_outdb = sqlOpen(filename, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
|
||||
|
||||
int oldVersion = sqlReadIntProperty(_outdb, "version");
|
||||
if ((oldVersion != 0) && (oldVersion != FLUX_VERSION_CURRENT))
|
||||
Error() << fmt::format("that flux file is version {}, but this client is for version {}",
|
||||
|
||||
@@ -27,8 +27,9 @@ public:
|
||||
virtual bool retryable() { return false; }
|
||||
};
|
||||
|
||||
extern void setHardwareFluxSourceRevolutions(int revolutions);
|
||||
extern void setHardwareFluxSourceRevolutions(double revolutions);
|
||||
extern void setHardwareFluxSourceDensity(bool high_density);
|
||||
extern void setHardwareFluxSourceSynced(bool synced);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -3,13 +3,24 @@
|
||||
#include "fluxmap.h"
|
||||
#include "usb.h"
|
||||
#include "fluxsource/fluxsource.h"
|
||||
#include "fmt/format.h"
|
||||
|
||||
FlagGroup hardwareFluxSourceFlags;
|
||||
|
||||
static IntFlag revolutions(
|
||||
static DoubleFlag revolutions(
|
||||
{ "--revolutions" },
|
||||
"read this many revolutions of the disk",
|
||||
1);
|
||||
1.25);
|
||||
|
||||
static BoolFlag synced(
|
||||
{ "--sync-with-index" },
|
||||
"whether to wait for an index pulse before started to read",
|
||||
false);
|
||||
|
||||
static IntFlag indexMode(
|
||||
{ "--index-mode" },
|
||||
"index pulse source (0=drive, 1=300 RPM fake source, 2=360 RPM fake source",
|
||||
0);
|
||||
|
||||
static bool high_density = false;
|
||||
|
||||
@@ -24,6 +35,10 @@ public:
|
||||
HardwareFluxSource(unsigned drive):
|
||||
_drive(drive)
|
||||
{
|
||||
usbSetDrive(_drive, high_density, indexMode);
|
||||
std::cerr << "Measuring rotational speed... " << std::flush;
|
||||
_oneRevolution = usbGetRotationalPeriod();
|
||||
std::cerr << fmt::format("{}ms\n", _oneRevolution / 1e6);
|
||||
}
|
||||
|
||||
~HardwareFluxSource()
|
||||
@@ -33,9 +48,9 @@ public:
|
||||
public:
|
||||
std::unique_ptr<Fluxmap> readFlux(int track, int side)
|
||||
{
|
||||
usbSetDrive(_drive, high_density);
|
||||
usbSetDrive(_drive, high_density, indexMode);
|
||||
usbSeek(track);
|
||||
Bytes crunched = usbRead(side, revolutions);
|
||||
Bytes crunched = usbRead(side, synced, revolutions * _oneRevolution);
|
||||
auto fluxmap = std::make_unique<Fluxmap>();
|
||||
fluxmap->appendBytes(crunched.uncrunch());
|
||||
return fluxmap;
|
||||
@@ -54,13 +69,19 @@ public:
|
||||
private:
|
||||
unsigned _drive;
|
||||
unsigned _revolutions;
|
||||
nanoseconds_t _oneRevolution;
|
||||
};
|
||||
|
||||
void setHardwareFluxSourceRevolutions(int revolutions)
|
||||
void setHardwareFluxSourceRevolutions(double revolutions)
|
||||
{
|
||||
::revolutions.setDefaultValue(revolutions);
|
||||
}
|
||||
|
||||
void setHardwareFluxSourceSynced(bool synced)
|
||||
{
|
||||
::synced.setDefaultValue(synced);
|
||||
}
|
||||
|
||||
std::unique_ptr<FluxSource> FluxSource::createHardwareFluxSource(unsigned drive)
|
||||
{
|
||||
return std::unique_ptr<FluxSource>(new HardwareFluxSource(drive));
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "flags.h"
|
||||
#include "usb.h"
|
||||
#include "fluxsource/fluxsource.h"
|
||||
#include "fluxsink/fluxsink.h"
|
||||
#include "reader.h"
|
||||
#include "fluxmap.h"
|
||||
#include "sql.h"
|
||||
@@ -18,7 +19,13 @@
|
||||
#include "imagewriter/imagewriter.h"
|
||||
#include "fmt/format.h"
|
||||
|
||||
FlagGroup readerFlags { &hardwareFluxSourceFlags, &fluxmapReaderFlags, &visualiserFlags };
|
||||
FlagGroup readerFlags
|
||||
{
|
||||
&hardwareFluxSourceFlags,
|
||||
&sqliteFluxSinkFlags,
|
||||
&fluxmapReaderFlags,
|
||||
&visualiserFlags
|
||||
};
|
||||
|
||||
static DataSpecFlag source(
|
||||
{ "--source", "-s" },
|
||||
@@ -46,7 +53,11 @@ static SettableFlag justRead(
|
||||
|
||||
static SettableFlag dumpRecords(
|
||||
{ "--dump-records" },
|
||||
"Dump the parsed records.");
|
||||
"Dump the parsed but undecoded records.");
|
||||
|
||||
static SettableFlag dumpSectors(
|
||||
{ "--dump-sectors" },
|
||||
"Dump the decoded sectors.");
|
||||
|
||||
static IntFlag retries(
|
||||
{ "--retries" },
|
||||
@@ -57,7 +68,7 @@ static SettableFlag highDensityFlag(
|
||||
{ "--high-density", "--hd" },
|
||||
"set the drive to high density mode");
|
||||
|
||||
static sqlite3* outdb;
|
||||
static std::unique_ptr<FluxSink> outputFluxSink;
|
||||
|
||||
void setReaderDefaultSource(const std::string& source)
|
||||
{
|
||||
@@ -82,8 +93,8 @@ void Track::readFluxmap()
|
||||
"{0} ms in {1} bytes\n",
|
||||
int(fluxmap->duration()/1e6),
|
||||
fluxmap->bytes());
|
||||
if (outdb)
|
||||
sqlWriteFlux(outdb, physicalTrack, physicalSide, *fluxmap);
|
||||
if (outputFluxSink)
|
||||
outputFluxSink->writeFlux(physicalTrack, physicalSide, *fluxmap);
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<Track>> readTracks()
|
||||
@@ -96,17 +107,8 @@ std::vector<std::unique_ptr<Track>> readTracks()
|
||||
|
||||
if (!destination.get().empty())
|
||||
{
|
||||
outdb = sqlOpen(destination, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
|
||||
std::cout << "Writing a copy of the flux to " << destination.get() << std::endl;
|
||||
sqlPrepareFlux(outdb);
|
||||
sqlStmt(outdb, "BEGIN;");
|
||||
sqlWriteIntProperty(outdb, "version", FLUX_VERSION_CURRENT);
|
||||
atexit([]()
|
||||
{
|
||||
sqlStmt(outdb, "COMMIT;");
|
||||
sqlClose(outdb);
|
||||
}
|
||||
);
|
||||
outputFluxSink = FluxSink::createSqliteFluxSink(destination.get());
|
||||
}
|
||||
|
||||
std::shared_ptr<FluxSource> fluxSource = FluxSource::create(spec);
|
||||
@@ -174,8 +176,6 @@ void readDiskCommand(AbstractDecoder& decoder)
|
||||
decoder.decodeToSectors(*track);
|
||||
|
||||
std::cout << " ";
|
||||
if (!track->sectors.empty())
|
||||
{
|
||||
std::cout << fmt::format("{} records, {} sectors; ",
|
||||
track->rawrecords.size(),
|
||||
track->sectors.size());
|
||||
@@ -191,9 +191,12 @@ void readDiskCommand(AbstractDecoder& decoder)
|
||||
}
|
||||
|
||||
bool hasBadSectors = false;
|
||||
std::set<unsigned> requiredSectors = decoder.requiredSectors(*track);
|
||||
for (const auto& i : readSectors)
|
||||
{
|
||||
const auto& sector = i.second;
|
||||
requiredSectors.erase(sector->logicalSector);
|
||||
|
||||
if (sector->status != Sector::OK)
|
||||
{
|
||||
std::cout << std::endl
|
||||
@@ -202,6 +205,12 @@ void readDiskCommand(AbstractDecoder& decoder)
|
||||
hasBadSectors = true;
|
||||
}
|
||||
}
|
||||
for (unsigned logicalSector : requiredSectors)
|
||||
{
|
||||
std::cout << "\n"
|
||||
<< " Required sector " << logicalSector << " missing; ";
|
||||
hasBadSectors = true;
|
||||
}
|
||||
|
||||
if (hasBadSectors)
|
||||
failures = false;
|
||||
@@ -211,7 +220,6 @@ void readDiskCommand(AbstractDecoder& decoder)
|
||||
|
||||
if (!hasBadSectors)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!track->fluxsource->retryable())
|
||||
break;
|
||||
@@ -219,10 +227,7 @@ void readDiskCommand(AbstractDecoder& decoder)
|
||||
std::cout << "giving up" << std::endl
|
||||
<< " ";
|
||||
else
|
||||
{
|
||||
std::cout << retry << " retries remaining" << std::endl;
|
||||
track->fluxsource->recalibrate();
|
||||
}
|
||||
}
|
||||
|
||||
if (dumpRecords)
|
||||
@@ -230,13 +235,27 @@ void readDiskCommand(AbstractDecoder& decoder)
|
||||
std::cout << "\nRaw (undecoded) records follow:\n\n";
|
||||
for (auto& record : track->rawrecords)
|
||||
{
|
||||
std::cout << fmt::format("I+{:.2f}us", record.position.ns() / 1000.0)
|
||||
<< std::endl;
|
||||
std::cout << fmt::format("I+{:.2f}us with {:.2f}us clock\n",
|
||||
record.position.ns() / 1000.0, record.clock / 1000.0);
|
||||
hexdump(std::cout, record.data);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
if (dumpSectors)
|
||||
{
|
||||
std::cout << "\nDecoded sectors follow:\n\n";
|
||||
for (auto& i : readSectors)
|
||||
{
|
||||
auto& sector = i.second;
|
||||
std::cout << fmt::format("{}.{:02}.{:02}: I+{:.2f}us with {:.2f}us clock\n",
|
||||
sector->logicalTrack, sector->logicalSide, sector->logicalSector,
|
||||
sector->position.ns() / 1000.0, sector->clock / 1000.0);
|
||||
hexdump(std::cout, sector->data);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
int size = 0;
|
||||
bool printedTrack = false;
|
||||
for (auto& i : readSectors)
|
||||
|
||||
100
lib/usb.cc
100
lib/usb.cc
@@ -44,6 +44,10 @@ static void usb_init()
|
||||
if (i < 0)
|
||||
Error() << "could not claim interface: " << usberror(i);
|
||||
|
||||
i = libusb_reset_device(device);
|
||||
if (i < 0)
|
||||
Error() << "could not reset device: " << usberror(i);
|
||||
|
||||
int version = usbGetVersion();
|
||||
if (version != FLUXENGINE_VERSION)
|
||||
Error() << "your FluxEngine firmware is at version " << version
|
||||
@@ -149,7 +153,7 @@ nanoseconds_t usbGetRotationalPeriod(void)
|
||||
usb_cmd_send(&f, f.f.size);
|
||||
|
||||
auto r = await_reply<struct speed_frame>(F_FRAME_MEASURE_SPEED_REPLY);
|
||||
return r->period_ms * 1000;
|
||||
return r->period_ms * 1000000;
|
||||
}
|
||||
|
||||
static int large_bulk_transfer(int ep, Bytes& bytes)
|
||||
@@ -161,11 +165,11 @@ static int large_bulk_transfer(int ep, Bytes& bytes)
|
||||
return len;
|
||||
}
|
||||
|
||||
void usbTestBulkTransport()
|
||||
void usbTestBulkWrite()
|
||||
{
|
||||
usb_init();
|
||||
|
||||
struct any_frame f = { .f = {.type = F_FRAME_BULK_TEST_CMD, .size = sizeof(f)} };
|
||||
struct any_frame f = { .f = {.type = F_FRAME_BULK_WRITE_TEST_CMD, .size = sizeof(f)} };
|
||||
usb_cmd_send(&f, f.f.size);
|
||||
|
||||
/* These must match the device. */
|
||||
@@ -180,9 +184,9 @@ void usbTestBulkTransport()
|
||||
|
||||
std::cout << "Transferred "
|
||||
<< bulk_buffer.size()
|
||||
<< " bytes in "
|
||||
<< " bytes from FluxEngine -> PC in "
|
||||
<< int(elapsed_time * 1000.0)
|
||||
<< " ("
|
||||
<< " ms ("
|
||||
<< int((bulk_buffer.size() / 1024.0) / elapsed_time)
|
||||
<< " kB/s)"
|
||||
<< std::endl;
|
||||
@@ -199,16 +203,56 @@ void usbTestBulkTransport()
|
||||
<< x << '.' << y << '.' << z << '.';
|
||||
}
|
||||
|
||||
await_reply<struct any_frame>(F_FRAME_BULK_TEST_REPLY);
|
||||
await_reply<struct any_frame>(F_FRAME_BULK_WRITE_TEST_REPLY);
|
||||
}
|
||||
|
||||
Bytes usbRead(int side, int revolutions)
|
||||
void usbTestBulkRead()
|
||||
{
|
||||
usb_init();
|
||||
|
||||
struct any_frame f = { .f = {.type = F_FRAME_BULK_READ_TEST_CMD, .size = sizeof(f)} };
|
||||
usb_cmd_send(&f, f.f.size);
|
||||
|
||||
/* These must match the device. */
|
||||
const int XSIZE = 64;
|
||||
const int YSIZE = 256;
|
||||
const int ZSIZE = 64;
|
||||
|
||||
Bytes bulk_buffer(XSIZE*YSIZE*ZSIZE);
|
||||
for (int x=0; x<XSIZE; x++)
|
||||
for (int y=0; y<YSIZE; y++)
|
||||
for (int z=0; z<ZSIZE; z++)
|
||||
{
|
||||
int offset = x*XSIZE*YSIZE + y*ZSIZE + z;
|
||||
bulk_buffer[offset] = uint8_t(x+y+z);
|
||||
}
|
||||
|
||||
double start_time = getCurrentTime();
|
||||
large_bulk_transfer(FLUXENGINE_DATA_OUT_EP, bulk_buffer);
|
||||
double elapsed_time = getCurrentTime() - start_time;
|
||||
|
||||
std::cout << "Transferred "
|
||||
<< bulk_buffer.size()
|
||||
<< " bytes from PC -> FluxEngine in "
|
||||
<< int(elapsed_time * 1000.0)
|
||||
<< " ms ("
|
||||
<< int((bulk_buffer.size() / 1024.0) / elapsed_time)
|
||||
<< " kB/s)"
|
||||
<< std::endl;
|
||||
|
||||
await_reply<struct any_frame>(F_FRAME_BULK_READ_TEST_REPLY);
|
||||
}
|
||||
|
||||
Bytes usbRead(int side, bool synced, nanoseconds_t readTime)
|
||||
{
|
||||
struct read_frame f = {
|
||||
.f = { .type = F_FRAME_READ_CMD, .size = sizeof(f) },
|
||||
.side = (uint8_t) side,
|
||||
.revolutions = (uint8_t) revolutions
|
||||
.synced = (uint8_t) synced
|
||||
};
|
||||
uint16_t milliseconds = readTime / 1e6;
|
||||
((uint8_t*)&f.milliseconds)[0] = milliseconds;
|
||||
((uint8_t*)&f.milliseconds)[1] = milliseconds >> 8;
|
||||
usb_cmd_send(&f, f.f.size);
|
||||
|
||||
auto fluxmap = std::unique_ptr<Fluxmap>(new Fluxmap);
|
||||
@@ -253,15 +297,51 @@ void usbErase(int side)
|
||||
await_reply<struct any_frame>(F_FRAME_ERASE_REPLY);
|
||||
}
|
||||
|
||||
void usbSetDrive(int drive, bool high_density)
|
||||
void usbSetDrive(int drive, bool high_density, int index_mode)
|
||||
{
|
||||
usb_init();
|
||||
|
||||
struct set_drive_frame f = {
|
||||
{ .type = F_FRAME_SET_DRIVE_CMD, .size = sizeof(f) },
|
||||
.drive_flags = (uint8_t)((drive ? DRIVE_1 : DRIVE_0) | (high_density ? DRIVE_HD : DRIVE_DD)),
|
||||
.drive = (uint8_t) drive,
|
||||
.high_density = high_density,
|
||||
.index_mode = (uint8_t) index_mode
|
||||
};
|
||||
usb_cmd_send(&f, f.f.size);
|
||||
await_reply<struct any_frame>(F_FRAME_SET_DRIVE_REPLY);
|
||||
}
|
||||
|
||||
/* Hacky: the board always operates in little-endian mode. */
|
||||
static uint16_t read_short_from_usb(uint16_t usb)
|
||||
{
|
||||
uint8_t* p = (uint8_t*)&usb;
|
||||
return p[0] | (p[1] << 8);
|
||||
}
|
||||
|
||||
static void convert_voltages_from_usb(const struct voltages& vin, struct voltages& vout)
|
||||
{
|
||||
vout.logic0_mv = read_short_from_usb(vin.logic0_mv);
|
||||
vout.logic1_mv = read_short_from_usb(vin.logic1_mv);
|
||||
}
|
||||
|
||||
void usbMeasureVoltages(struct voltages_frame* voltages)
|
||||
{
|
||||
usb_init();
|
||||
|
||||
struct any_frame f = {
|
||||
{ .type = F_FRAME_MEASURE_VOLTAGES_CMD, .size = sizeof(f) },
|
||||
};
|
||||
usb_cmd_send(&f, f.f.size);
|
||||
|
||||
struct voltages_frame* r = await_reply<struct voltages_frame>(F_FRAME_MEASURE_VOLTAGES_REPLY);
|
||||
convert_voltages_from_usb(r->input_both_off, voltages->input_both_off);
|
||||
convert_voltages_from_usb(r->input_drive_0_selected, voltages->input_drive_0_selected);
|
||||
convert_voltages_from_usb(r->input_drive_1_selected, voltages->input_drive_1_selected);
|
||||
convert_voltages_from_usb(r->input_drive_0_running, voltages->input_drive_0_running);
|
||||
convert_voltages_from_usb(r->input_drive_1_running, voltages->input_drive_1_running);
|
||||
convert_voltages_from_usb(r->output_both_off, voltages->output_both_off);
|
||||
convert_voltages_from_usb(r->output_drive_0_selected, voltages->output_drive_0_selected);
|
||||
convert_voltages_from_usb(r->output_drive_1_selected, voltages->output_drive_1_selected);
|
||||
convert_voltages_from_usb(r->output_drive_0_running, voltages->output_drive_0_running);
|
||||
convert_voltages_from_usb(r->output_drive_1_running, voltages->output_drive_1_running);
|
||||
}
|
||||
|
||||
@@ -8,10 +8,12 @@ extern int usbGetVersion();
|
||||
extern void usbRecalibrate();
|
||||
extern void usbSeek(int track);
|
||||
extern nanoseconds_t usbGetRotationalPeriod();
|
||||
extern void usbTestBulkTransport();
|
||||
extern Bytes usbRead(int side, int revolutions);
|
||||
extern void usbTestBulkWrite();
|
||||
extern void usbTestBulkRead();
|
||||
extern Bytes usbRead(int side, bool synced, nanoseconds_t readTime);
|
||||
extern void usbWrite(int side, const Bytes& bytes);
|
||||
extern void usbErase(int side);
|
||||
extern void usbSetDrive(int drive, bool high_density);
|
||||
extern void usbSetDrive(int drive, bool high_density, int index_mode);
|
||||
extern void usbMeasureVoltages(struct voltages_frame* voltages);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include "sector.h"
|
||||
#include "sectorset.h"
|
||||
|
||||
FlagGroup writerFlags { &hardwareFluxSourceFlags };
|
||||
FlagGroup writerFlags { &hardwareFluxSourceFlags, &hardwareFluxSinkFlags };
|
||||
|
||||
static DataSpecFlag dest(
|
||||
{ "--dest", "-d" },
|
||||
@@ -84,7 +84,9 @@ void writeTracks(
|
||||
}
|
||||
else
|
||||
{
|
||||
fluxmap->precompensate(PRECOMPENSATION_THRESHOLD_TICKS, 2);
|
||||
/* Precompensation actually seems to make things worse, so let's leave
|
||||
* it disabled for now. */
|
||||
//fluxmap->precompensate(PRECOMPENSATION_THRESHOLD_TICKS, 2);
|
||||
if (outdb)
|
||||
sqlWriteFlux(outdb, location.track, location.side, *fluxmap);
|
||||
else
|
||||
|
||||
47
mkninja.sh
47
mkninja.sh
@@ -44,18 +44,27 @@ buildlibrary() {
|
||||
esac
|
||||
done
|
||||
|
||||
local objs
|
||||
objs=
|
||||
local oobjs
|
||||
local dobjs
|
||||
oobjs=
|
||||
dobjs=
|
||||
for src in "$@"; do
|
||||
local obj
|
||||
obj="$OBJDIR/${src%%.c*}.o"
|
||||
objs="$objs $obj"
|
||||
obj="$OBJDIR/opt/${src%%.c*}.o"
|
||||
oobjs="$oobjs $obj"
|
||||
|
||||
echo build $obj : cxx $src
|
||||
echo " flags=$flags"
|
||||
echo " flags=$flags $COPTFLAGS"
|
||||
|
||||
obj="$OBJDIR/dbg/${src%%.c*}.o"
|
||||
dobjs="$dobjs $obj"
|
||||
|
||||
echo build $obj : cxx $src
|
||||
echo " flags=$flags $CDBGFLAGS"
|
||||
done
|
||||
|
||||
echo build $OBJDIR/$lib : library $objs
|
||||
echo build $OBJDIR/opt/$lib : library $oobjs
|
||||
echo build $OBJDIR/dbg/$lib : library $dobjs
|
||||
}
|
||||
|
||||
buildprogram() {
|
||||
@@ -77,16 +86,21 @@ buildprogram() {
|
||||
esac
|
||||
done
|
||||
|
||||
local objs
|
||||
objs=
|
||||
local oobjs
|
||||
local dobjs
|
||||
oobjs=
|
||||
dobjs=
|
||||
for src in "$@"; do
|
||||
objs="$objs $OBJDIR/$src"
|
||||
oobjs="$oobjs $OBJDIR/opt/$src"
|
||||
dobjs="$dobjs $OBJDIR/dbg/$src"
|
||||
done
|
||||
|
||||
echo build $prog-debug$EXTENSION : link $objs
|
||||
echo " flags=$flags"
|
||||
echo build $prog-debug$EXTENSION : link $dobjs
|
||||
echo " flags=$flags $LDDBGFLAGS"
|
||||
|
||||
echo build $prog$EXTENSION : link $oobjs
|
||||
echo " flags=$flags $LDOPTFLAGS"
|
||||
|
||||
echo build $prog$EXTENSION : strip $prog-debug$EXTENSION
|
||||
}
|
||||
|
||||
buildsimpleprogram() {
|
||||
@@ -145,6 +159,8 @@ buildlibrary libbackend.a \
|
||||
lib/imagewriter/ldbsimagewriter.cc \
|
||||
arch/aeslanier/decoder.cc \
|
||||
arch/amiga/decoder.cc \
|
||||
arch/amiga/encoder.cc \
|
||||
arch/amiga/amiga.cc \
|
||||
arch/apple2/decoder.cc \
|
||||
arch/brother/decoder.cc \
|
||||
arch/brother/encoder.cc \
|
||||
@@ -152,6 +168,7 @@ buildlibrary libbackend.a \
|
||||
arch/f85/decoder.cc \
|
||||
arch/fb100/decoder.cc \
|
||||
arch/ibm/decoder.cc \
|
||||
arch/ibm/encoder.cc \
|
||||
arch/macintosh/decoder.cc \
|
||||
arch/mx/decoder.cc \
|
||||
arch/victor9k/decoder.cc \
|
||||
@@ -211,9 +228,12 @@ buildlibrary libfrontend.a \
|
||||
src/fe-rpm.cc \
|
||||
src/fe-scptoflux.cc \
|
||||
src/fe-seek.cc \
|
||||
src/fe-testbulktransport.cc \
|
||||
src/fe-testbandwidth.cc \
|
||||
src/fe-testvoltages.cc \
|
||||
src/fe-upgradefluxfile.cc \
|
||||
src/fe-writeamiga.cc \
|
||||
src/fe-writebrother.cc \
|
||||
src/fe-writeibm.cc \
|
||||
src/fe-writeflux.cc \
|
||||
src/fe-writetestpattern.cc \
|
||||
src/fluxengine.cc \
|
||||
@@ -250,3 +270,4 @@ runtest fluxpattern-test tests/fluxpattern.cc
|
||||
runtest fmmfm-test tests/fmmfm.cc
|
||||
runtest kryoflux-test tests/kryoflux.cc
|
||||
runtest ldbs-test tests/ldbs.cc
|
||||
runtest amiga-test tests/amiga.cc
|
||||
|
||||
45
protocol.h
45
protocol.h
@@ -3,7 +3,7 @@
|
||||
|
||||
enum
|
||||
{
|
||||
FLUXENGINE_VERSION = 8,
|
||||
FLUXENGINE_VERSION = 12,
|
||||
|
||||
FLUXENGINE_VID = 0x1209,
|
||||
FLUXENGINE_PID = 0x6e00,
|
||||
@@ -50,8 +50,10 @@ enum
|
||||
F_FRAME_SEEK_REPLY, /* any_frame */
|
||||
F_FRAME_MEASURE_SPEED_CMD, /* any_frame */
|
||||
F_FRAME_MEASURE_SPEED_REPLY, /* speed_frame */
|
||||
F_FRAME_BULK_TEST_CMD, /* any_frame */
|
||||
F_FRAME_BULK_TEST_REPLY, /* any_frame */
|
||||
F_FRAME_BULK_WRITE_TEST_CMD, /* any_frame */
|
||||
F_FRAME_BULK_WRITE_TEST_REPLY, /* any_frame */
|
||||
F_FRAME_BULK_READ_TEST_CMD, /* any_frame */
|
||||
F_FRAME_BULK_READ_TEST_REPLY, /* any_frame */
|
||||
F_FRAME_READ_CMD, /* read_frame */
|
||||
F_FRAME_READ_REPLY, /* any_frame */
|
||||
F_FRAME_WRITE_CMD, /* write_frame */
|
||||
@@ -62,6 +64,8 @@ enum
|
||||
F_FRAME_RECALIBRATE_REPLY, /* any_frame */
|
||||
F_FRAME_SET_DRIVE_CMD, /* setdrive_frame */
|
||||
F_FRAME_SET_DRIVE_REPLY, /* any_frame */
|
||||
F_FRAME_MEASURE_VOLTAGES_CMD, /* any_frame */
|
||||
F_FRAME_MEASURE_VOLTAGES_REPLY, /* voltages_frame */
|
||||
};
|
||||
|
||||
enum
|
||||
@@ -73,6 +77,13 @@ enum
|
||||
F_ERROR_INTERNAL,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
F_INDEX_REAL,
|
||||
F_INDEX_300,
|
||||
F_INDEX_360
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
F_OP_PULSE = 0x80,
|
||||
@@ -124,7 +135,8 @@ struct read_frame
|
||||
{
|
||||
struct frame_header f;
|
||||
uint8_t side;
|
||||
uint8_t revolutions;
|
||||
uint8_t synced;
|
||||
uint16_t milliseconds;
|
||||
};
|
||||
|
||||
struct write_frame
|
||||
@@ -143,7 +155,30 @@ struct erase_frame
|
||||
struct set_drive_frame
|
||||
{
|
||||
struct frame_header f;
|
||||
uint8_t drive_flags;
|
||||
uint8_t drive;
|
||||
uint8_t high_density;
|
||||
uint8_t index_mode;
|
||||
};
|
||||
|
||||
struct voltages
|
||||
{
|
||||
uint16_t logic0_mv;
|
||||
uint16_t logic1_mv;
|
||||
};
|
||||
|
||||
struct voltages_frame
|
||||
{
|
||||
struct frame_header f;
|
||||
struct voltages output_both_off;
|
||||
struct voltages output_drive_0_selected;
|
||||
struct voltages output_drive_1_selected;
|
||||
struct voltages output_drive_0_running;
|
||||
struct voltages output_drive_1_running;
|
||||
struct voltages input_both_off;
|
||||
struct voltages input_drive_0_selected;
|
||||
struct voltages input_drive_1_selected;
|
||||
struct voltages input_drive_0_running;
|
||||
struct voltages input_drive_1_running;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -85,7 +85,7 @@ int mainConvertFluxToScp(int argc, const char* argv[])
|
||||
fileheader.file_id[0] = 'S';
|
||||
fileheader.file_id[1] = 'C';
|
||||
fileheader.file_id[2] = 'P';
|
||||
fileheader.file_id[3] = 0x18; /* Version 1.8 of the spec */
|
||||
fileheader.version = 0x18; /* Version 1.8 of the spec */
|
||||
fileheader.type = diskType;
|
||||
fileheader.revolutions = 5;
|
||||
fileheader.start_track = 0;
|
||||
|
||||
@@ -12,11 +12,6 @@
|
||||
|
||||
static FlagGroup flags { &readerFlags };
|
||||
|
||||
static StringFlag outputFilename(
|
||||
{ "--output", "-o" },
|
||||
"The output image file to write to.",
|
||||
"aeslanier.img");
|
||||
|
||||
int mainReadAESLanier(int argc, const char* argv[])
|
||||
{
|
||||
setReaderDefaultSource(":t=0-79:s=0");
|
||||
|
||||
@@ -7,28 +7,34 @@
|
||||
#include "sector.h"
|
||||
#include "sectorset.h"
|
||||
#include "record.h"
|
||||
#include "dataspec.h"
|
||||
#include "ibm/ibm.h"
|
||||
#include "fmt/format.h"
|
||||
|
||||
static FlagGroup flags { &readerFlags };
|
||||
|
||||
static IntFlag sectorIdBase(
|
||||
{ "--sector-id-base" },
|
||||
{ "--ibm-sector-id-base" },
|
||||
"Sector ID of the first sector.",
|
||||
1);
|
||||
|
||||
static BoolFlag ignoreSideByte(
|
||||
{ "--ignore-side-byte" },
|
||||
{ "--ibm-ignore-side-byte" },
|
||||
"Ignore the side byte in the sector ID, and use the physical side instead.",
|
||||
false);
|
||||
|
||||
static RangeFlag requiredSectors(
|
||||
{ "--ibm-required-sectors" },
|
||||
"A comma seperated list or range of sectors which must be on each track.",
|
||||
"");
|
||||
|
||||
int mainReadIBM(int argc, const char* argv[])
|
||||
{
|
||||
setReaderDefaultSource(":t=0-79:s=0-1");
|
||||
setReaderDefaultOutput("ibm.img");
|
||||
flags.parseFlags(argc, argv);
|
||||
|
||||
IbmDecoder decoder(sectorIdBase, ignoreSideByte);
|
||||
IbmDecoder decoder(sectorIdBase, ignoreSideByte, requiredSectors);
|
||||
readDiskCommand(decoder);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include "sector.h"
|
||||
#include "sectorset.h"
|
||||
#include "record.h"
|
||||
#include <fmt/format.h>
|
||||
|
||||
static FlagGroup flags { &readerFlags };
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "flags.h"
|
||||
#include "usb.h"
|
||||
#include "dataspec.h"
|
||||
#include "protocol.h"
|
||||
|
||||
static FlagGroup flags;
|
||||
|
||||
@@ -15,9 +16,18 @@ int mainRpm(int argc, const char* argv[])
|
||||
flags.parseFlags(argc, argv);
|
||||
|
||||
FluxSpec spec(source);
|
||||
usbSetDrive(spec.drive, false);
|
||||
usbSetDrive(spec.drive, false, F_INDEX_REAL);
|
||||
nanoseconds_t period = usbGetRotationalPeriod();
|
||||
std::cout << "Rotational period is " << period/1000 << " ms (" << 60e6/period << " rpm)" << std::endl;
|
||||
if (period != 0)
|
||||
std::cout << "Rotational period is " << period/1000000 << " ms (" << 60e9/period << " rpm)" << std::endl;
|
||||
else
|
||||
{
|
||||
std::cout << "No index pulses detected from the disk. Common causes of this are:\n"
|
||||
" - no drive is connected\n"
|
||||
" - the drive doesn't have an index sensor (e.g. BBC Micro drives)\n"
|
||||
" - the disk has no index holes (e.g. reversed flippy disks)\n"
|
||||
" - (most common) no disk is inserted in the drive!\n";
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "globals.h"
|
||||
#include "flags.h"
|
||||
#include "usb.h"
|
||||
#include "protocol.h"
|
||||
|
||||
static FlagGroup flags;
|
||||
|
||||
@@ -18,7 +19,7 @@ int mainSeek(int argc, const char* argv[])
|
||||
{
|
||||
flags.parseFlags(argc, argv);
|
||||
|
||||
usbSetDrive(drive, false);
|
||||
usbSetDrive(drive, false, F_INDEX_REAL);
|
||||
usbSeek(track);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -4,9 +4,10 @@
|
||||
|
||||
static FlagGroup flags;
|
||||
|
||||
int mainTestBulkTransport(int argc, const char* argv[])
|
||||
int mainTestBandwidth(int argc, const char* argv[])
|
||||
{
|
||||
flags.parseFlags(argc, argv);
|
||||
usbTestBulkTransport();
|
||||
usbTestBulkWrite();
|
||||
usbTestBulkRead();
|
||||
return 0;
|
||||
}
|
||||
47
src/fe-testvoltages.cc
Normal file
47
src/fe-testvoltages.cc
Normal file
@@ -0,0 +1,47 @@
|
||||
#include "globals.h"
|
||||
#include "flags.h"
|
||||
#include "usb.h"
|
||||
#include "protocol.h"
|
||||
#include <fmt/format.h>
|
||||
|
||||
static FlagGroup flags;
|
||||
|
||||
static std::string display_voltages(struct voltages& v)
|
||||
{
|
||||
return fmt::format(
|
||||
" Logic 1 / 0: {:.2f}V / {:.2f}V\n",
|
||||
v.logic0_mv / 1000.0,
|
||||
v.logic1_mv / 1000.0);
|
||||
}
|
||||
|
||||
int mainTestVoltages(int argc, const char* argv[])
|
||||
{
|
||||
flags.parseFlags(argc, argv);
|
||||
struct voltages_frame f;
|
||||
usbMeasureVoltages(&f);
|
||||
|
||||
std::cout << "Output voltages:\n"
|
||||
<< " Both drives deselected\n"
|
||||
<< display_voltages(f.output_both_off)
|
||||
<< " Drive 0 selected\n"
|
||||
<< display_voltages(f.output_drive_0_selected)
|
||||
<< " Drive 1 selected\n"
|
||||
<< display_voltages(f.output_drive_1_selected)
|
||||
<< " Drive 0 running\n"
|
||||
<< display_voltages(f.output_drive_0_running)
|
||||
<< " Drive 1 running\n"
|
||||
<< display_voltages(f.output_drive_1_running)
|
||||
<< "Input voltages:\n"
|
||||
<< " Both drives deselected\n"
|
||||
<< display_voltages(f.input_both_off)
|
||||
<< " Drive 0 selected\n"
|
||||
<< display_voltages(f.input_drive_0_selected)
|
||||
<< " Drive 1 selected\n"
|
||||
<< display_voltages(f.input_drive_1_selected)
|
||||
<< " Drive 0 running\n"
|
||||
<< display_voltages(f.input_drive_0_running)
|
||||
<< " Drive 1 running\n"
|
||||
<< display_voltages(f.input_drive_1_running);
|
||||
|
||||
return 0;
|
||||
}
|
||||
23
src/fe-writeamiga.cc
Normal file
23
src/fe-writeamiga.cc
Normal file
@@ -0,0 +1,23 @@
|
||||
#include "globals.h"
|
||||
#include "flags.h"
|
||||
#include "decoders/decoders.h"
|
||||
#include "amiga/amiga.h"
|
||||
#include "writer.h"
|
||||
#include "fmt/format.h"
|
||||
#include "image.h"
|
||||
#include <fstream>
|
||||
|
||||
static FlagGroup flags { &writerFlags, &amigaEncoderFlags };
|
||||
|
||||
int mainWriteAmiga(int argc, const char* argv[])
|
||||
{
|
||||
setWriterDefaultInput(":c=80:h=2:s=11:b=512");
|
||||
setWriterDefaultDest(":d=0:t=0-79:s=0-1");
|
||||
flags.parseFlags(argc, argv);
|
||||
|
||||
AmigaEncoder encoder;
|
||||
writeDiskCommand(encoder);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
139
src/fe-writeibm.cc
Normal file
139
src/fe-writeibm.cc
Normal file
@@ -0,0 +1,139 @@
|
||||
#include "globals.h"
|
||||
#include "flags.h"
|
||||
#include "decoders/decoders.h"
|
||||
#include "encoders/encoders.h"
|
||||
#include "ibm/ibm.h"
|
||||
#include "writer.h"
|
||||
#include "fmt/format.h"
|
||||
#include "image.h"
|
||||
#include <fstream>
|
||||
|
||||
static FlagGroup flags { &writerFlags };
|
||||
|
||||
static IntFlag trackLengthMs(
|
||||
{ "--ibm-track-length-ms" },
|
||||
"Length of a track in milliseconds.",
|
||||
0);
|
||||
|
||||
static IntFlag sectorSize(
|
||||
{ "--ibm-sector-size" },
|
||||
"Size of the sectors to write (bytes).",
|
||||
0);
|
||||
|
||||
static BoolFlag emitIam(
|
||||
{ "--ibm-emit-iam" },
|
||||
"Whether to emit an IAM record at the start of the track.",
|
||||
false);
|
||||
|
||||
static IntFlag startSectorId(
|
||||
{ "--ibm-start-sector-id" },
|
||||
"Sector ID of first sector.",
|
||||
1);
|
||||
|
||||
static IntFlag clockRateKhz(
|
||||
{ "--ibm-clock-rate-khz" },
|
||||
"Clock rate of data to write.",
|
||||
0);
|
||||
|
||||
static BoolFlag useFm(
|
||||
{ "--ibm-use-fm" },
|
||||
"Write in FM mode, rather than MFM.",
|
||||
false);
|
||||
|
||||
static HexIntFlag idamByte(
|
||||
{ "--ibm-idam-byte" },
|
||||
"16-bit RAW bit pattern to use for the IDAM ID byte",
|
||||
0);
|
||||
|
||||
static HexIntFlag damByte(
|
||||
{ "--ibm-dam-byte" },
|
||||
"16-bit RAW bit pattern to use for the DAM ID byte",
|
||||
0);
|
||||
|
||||
static IntFlag gap0(
|
||||
{ "--ibm-gap0-bytes" },
|
||||
"Size of gap 0 (the pre-index gap)",
|
||||
0);
|
||||
|
||||
static IntFlag gap1(
|
||||
{ "--ibm-gap1-bytes" },
|
||||
"Size of gap 1 (the post-index gap).",
|
||||
0);
|
||||
|
||||
static IntFlag gap2(
|
||||
{ "--ibm-gap2-bytes" },
|
||||
"Size of gap 2 (the post-ID gap).",
|
||||
0);
|
||||
|
||||
static IntFlag gap3(
|
||||
{ "--ibm-gap3-bytes" },
|
||||
"Size of gap 3 (the post-data or format gap).",
|
||||
0);
|
||||
|
||||
static StringFlag sectorSkew(
|
||||
{ "--ibm-sector-skew" },
|
||||
"Order to emit sectors.",
|
||||
"");
|
||||
|
||||
static ActionFlag preset1440(
|
||||
{ "--ibm-preset-1440" },
|
||||
"Preset parameters to a 3.5\" 1440kB disk.",
|
||||
[] {
|
||||
setWriterDefaultInput(":c=80:h=2:s=18:b=512");
|
||||
trackLengthMs.setDefaultValue(200);
|
||||
sectorSize.setDefaultValue(512);
|
||||
emitIam.setDefaultValue(true);
|
||||
clockRateKhz.setDefaultValue(500);
|
||||
idamByte.setDefaultValue(0x5554);
|
||||
damByte.setDefaultValue(0x5545);
|
||||
gap0.setDefaultValue(80);
|
||||
gap1.setDefaultValue(50);
|
||||
gap2.setDefaultValue(22);
|
||||
gap3.setDefaultValue(108);
|
||||
sectorSkew.setDefaultValue("0123456789abcdefgh");
|
||||
});
|
||||
|
||||
static ActionFlag preset720(
|
||||
{ "--ibm-preset-720" },
|
||||
"Preset parameters to a 3.5\" 720kB disk.",
|
||||
[] {
|
||||
setWriterDefaultInput(":c=80:h=2:s=9:b=512");
|
||||
trackLengthMs.setDefaultValue(200);
|
||||
sectorSize.setDefaultValue(512);
|
||||
emitIam.setDefaultValue(true);
|
||||
clockRateKhz.setDefaultValue(250);
|
||||
idamByte.setDefaultValue(0x5554);
|
||||
damByte.setDefaultValue(0x5545);
|
||||
gap0.setDefaultValue(80);
|
||||
gap1.setDefaultValue(50);
|
||||
gap2.setDefaultValue(22);
|
||||
gap3.setDefaultValue(80);
|
||||
sectorSkew.setDefaultValue("012345678");
|
||||
});
|
||||
|
||||
int mainWriteIbm(int argc, const char* argv[])
|
||||
{
|
||||
setWriterDefaultDest(":d=0:t=0-79:s=0-1");
|
||||
flags.parseFlags(argc, argv);
|
||||
|
||||
IbmParameters parameters;
|
||||
parameters.trackLengthMs = trackLengthMs;
|
||||
parameters.sectorSize = sectorSize;
|
||||
parameters.emitIam = emitIam;
|
||||
parameters.startSectorId = startSectorId;
|
||||
parameters.clockRateKhz = clockRateKhz;
|
||||
parameters.useFm = useFm;
|
||||
parameters.idamByte = idamByte;
|
||||
parameters.damByte = damByte;
|
||||
parameters.gap0 = gap0;
|
||||
parameters.gap1 = gap1;
|
||||
parameters.gap2 = gap2;
|
||||
parameters.gap3 = gap3;
|
||||
parameters.sectorSkew = sectorSkew;
|
||||
|
||||
IbmEncoder encoder(parameters);
|
||||
writeDiskCommand(encoder);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -26,9 +26,12 @@ extern command_cb mainReadVictor9K;
|
||||
extern command_cb mainReadZilogMCZ;
|
||||
extern command_cb mainRpm;
|
||||
extern command_cb mainSeek;
|
||||
extern command_cb mainTestBulkTransport;
|
||||
extern command_cb mainTestBandwidth;
|
||||
extern command_cb mainTestVoltages;
|
||||
extern command_cb mainUpgradeFluxFile;
|
||||
extern command_cb mainWriteAmiga;
|
||||
extern command_cb mainWriteBrother;
|
||||
extern command_cb mainWriteIbm;
|
||||
extern command_cb mainWriteFlux;
|
||||
extern command_cb mainWriteTestPattern;
|
||||
|
||||
@@ -42,6 +45,7 @@ struct Command
|
||||
static command_cb mainRead;
|
||||
static command_cb mainWrite;
|
||||
static command_cb mainConvert;
|
||||
static command_cb mainTest;
|
||||
|
||||
static std::vector<Command> commands =
|
||||
{
|
||||
@@ -51,7 +55,7 @@ static std::vector<Command> commands =
|
||||
{ "read", mainRead, "Reads a disk, producing a sector image.", },
|
||||
{ "rpm", mainRpm, "Measures the disk rotational speed.", },
|
||||
{ "seek", mainSeek, "Moves the disk head.", },
|
||||
{ "testbulktransport", mainTestBulkTransport, "Measures your USB bandwidth.", },
|
||||
{ "test", mainTest, "Various testing commands.", },
|
||||
{ "upgradefluxfile", mainUpgradeFluxFile, "Upgrades a flux file from a previous version of this software.", },
|
||||
{ "write", mainWrite, "Writes a sector image to a disk.", },
|
||||
{ "writeflux", mainWriteFlux, "Writes a raw flux file. Warning: you can't use this to copy disks.", },
|
||||
@@ -79,7 +83,9 @@ static std::vector<Command> readables =
|
||||
|
||||
static std::vector<Command> writeables =
|
||||
{
|
||||
{ "amiga", mainWriteAmiga, "Writes Amiga disks.", },
|
||||
{ "brother", mainWriteBrother, "Writes 120kB and 240kB Brother word processor disks.", },
|
||||
{ "ibm", mainWriteIbm, "Writes the ubiquitous IBM format disks.", },
|
||||
};
|
||||
|
||||
static std::vector<Command> convertables =
|
||||
@@ -91,6 +97,12 @@ static std::vector<Command> convertables =
|
||||
{ "fluxtovcd", mainConvertFluxToVcd, "Converts (one track of a) flux file to a VCD file.", },
|
||||
};
|
||||
|
||||
static std::vector<Command> testables =
|
||||
{
|
||||
{ "bandwidth", mainTestBandwidth, "Measures your USB bandwidth.", },
|
||||
{ "voltages", mainTestVoltages, "Measures the FDD bus voltages.", },
|
||||
};
|
||||
|
||||
static void extendedHelp(std::vector<Command>& subcommands, const std::string& command)
|
||||
{
|
||||
std::cout << "fluxengine: syntax: fluxengine " << command << " <format> [<flags>...]\n"
|
||||
@@ -131,6 +143,9 @@ static int mainWrite(int argc, const char* argv[])
|
||||
static int mainConvert(int argc, const char* argv[])
|
||||
{ return mainExtended(convertables, "convert", argc, argv); }
|
||||
|
||||
static int mainTest(int argc, const char* argv[])
|
||||
{ return mainExtended(testables, "test", argc, argv); }
|
||||
|
||||
static void help()
|
||||
{
|
||||
std::cout << "fluxengine: syntax: fluxengine <command> [<flags>...]\n"
|
||||
|
||||
38
tests/amiga.cc
Normal file
38
tests/amiga.cc
Normal file
@@ -0,0 +1,38 @@
|
||||
#include "globals.h"
|
||||
#include "bytes.h"
|
||||
#include "record.h"
|
||||
#include "decoders/decoders.h"
|
||||
#include "arch/amiga/amiga.h"
|
||||
#include <assert.h>
|
||||
|
||||
static const Bytes testData = {
|
||||
0x52, /* 0101 0010 */
|
||||
0xff, /* 1111 1111 */
|
||||
0x4a, /* 0100 1010 */
|
||||
0x22, /* 0010 0010 */
|
||||
};
|
||||
static const Bytes testDataInterleaved = {
|
||||
0x1f, /* 0001 1111 */
|
||||
0x35, /* 0011 0101 */
|
||||
0xcf, /* 1100 1111 */
|
||||
0x80, /* 1000 0000 */
|
||||
};
|
||||
|
||||
static void testInterleave(void)
|
||||
{
|
||||
Bytes interleaved = amigaInterleave(testData);
|
||||
assert(interleaved == testDataInterleaved);
|
||||
}
|
||||
|
||||
static void testDeinterleave(void)
|
||||
{
|
||||
Bytes deinterleaved = amigaDeinterleave(testDataInterleaved);
|
||||
assert(deinterleaved == testData);
|
||||
}
|
||||
|
||||
int main(int argc, const char* argv[])
|
||||
{
|
||||
testDeinterleave();
|
||||
testInterleave();
|
||||
return 0;
|
||||
}
|
||||
@@ -115,6 +115,15 @@ static void test_slice()
|
||||
assert((bs == Bytes{ 0, 0 }));
|
||||
}
|
||||
|
||||
static void test_tobits()
|
||||
{
|
||||
Bytes b = {1, 2};
|
||||
assert(b.toBits() == (std::vector<bool>{
|
||||
false, false, false, false, false, false, false, true,
|
||||
false, false, false, false, false, false, true, false
|
||||
}));
|
||||
}
|
||||
|
||||
int main(int argc, const char* argv[])
|
||||
{
|
||||
test_bounds();
|
||||
@@ -123,5 +132,6 @@ int main(int argc, const char* argv[])
|
||||
test_reads();
|
||||
test_writes();
|
||||
test_slice();
|
||||
test_tobits();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ static uint8_t outputbuffer[64];
|
||||
static void test_crunch()
|
||||
{
|
||||
crunch_state_t cs = {};
|
||||
Bytes inputdata = { 0x01, 0x7f, 0x80, 0x81, 0x01 };
|
||||
Bytes inputdata = { 0x01, 0x7f, 0x80, 0x05, 0x80, 0x81, 0x01 };
|
||||
cs.inputptr = inputdata.begin();
|
||||
cs.inputlen = inputdata.size();
|
||||
cs.outputptr = outputbuffer;
|
||||
@@ -16,13 +16,13 @@ static void test_crunch()
|
||||
donecrunch(&cs);
|
||||
Bytes outputdata(outputbuffer, cs.outputptr - outputbuffer);
|
||||
|
||||
assert((outputdata == Bytes{ 0x01, 0x7f, 0xb0, 0x10 }));
|
||||
assert((outputdata == Bytes{ 0x01, 0x7f, 0xc5, 0x94, 0x04 }));
|
||||
}
|
||||
|
||||
static void test_uncrunch()
|
||||
{
|
||||
crunch_state_t cs = {};
|
||||
Bytes inputdata = { 0x01, 0x7f, 0xb0, 0x10 };
|
||||
Bytes inputdata = { 0x01, 0x7f, 0xc5, 0x94, 0x04 };
|
||||
cs.inputptr = inputdata.begin();
|
||||
cs.inputlen = inputdata.size();
|
||||
cs.outputptr = outputbuffer;
|
||||
@@ -31,7 +31,7 @@ static void test_uncrunch()
|
||||
doneuncrunch(&cs);
|
||||
Bytes outputdata(outputbuffer, cs.outputptr - outputbuffer);
|
||||
|
||||
assert((outputdata == Bytes { 0x01, 0x7f, 0x80, 0x81, 0x01 }));
|
||||
assert((outputdata == Bytes { 0x01, 0x7f, 0x80, 0x05, 0x80, 0x81, 0x01 }));
|
||||
}
|
||||
|
||||
int main(int argc, const char* argv[])
|
||||
|
||||
@@ -13,6 +13,28 @@ static void test_split(void)
|
||||
== std::vector<std::string>{"", "2", ""}));
|
||||
assert((DataSpec::split("2", ",")
|
||||
== std::vector<std::string>{"2"}));
|
||||
assert((DataSpec::split("", ",")
|
||||
== std::vector<std::string>()));
|
||||
}
|
||||
|
||||
static void test_parserange(void)
|
||||
{
|
||||
assert(DataSpec::parseRange("")
|
||||
== std::set<unsigned>());
|
||||
assert(DataSpec::parseRange("1")
|
||||
== std::set<unsigned>({1}));
|
||||
assert(DataSpec::parseRange("1,3,5")
|
||||
== std::set<unsigned>({1, 3, 5}));
|
||||
assert(DataSpec::parseRange("1,1,1")
|
||||
== std::set<unsigned>({1}));
|
||||
assert(DataSpec::parseRange("2-3")
|
||||
== std::set<unsigned>({2, 3}));
|
||||
assert(DataSpec::parseRange("2+3")
|
||||
== std::set<unsigned>({2, 3, 4}));
|
||||
assert(DataSpec::parseRange("2+3x2")
|
||||
== std::set<unsigned>({2, 4}));
|
||||
assert(DataSpec::parseRange("9,2+3x2")
|
||||
== std::set<unsigned>({2, 4, 9}));
|
||||
}
|
||||
|
||||
static void test_parsemod(void)
|
||||
@@ -104,6 +126,7 @@ static void test_imagespec(void)
|
||||
int main(int argc, const char* argv[])
|
||||
{
|
||||
test_split();
|
||||
test_parserange();
|
||||
test_parsemod();
|
||||
test_fluxspec();
|
||||
test_imagespec();
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#include "decoders/decoders.h"
|
||||
#include <assert.h>
|
||||
|
||||
int main(int argc, const char* argv[])
|
||||
static void testDecode(void)
|
||||
{
|
||||
assert(decodeFmMfm(
|
||||
std::vector<bool>{
|
||||
@@ -36,6 +36,100 @@ int main(int argc, const char* argv[])
|
||||
true, false,
|
||||
}
|
||||
) == Bytes{ 0x80 });
|
||||
}
|
||||
|
||||
static std::vector<bool> wrappedEncodeMfm(const Bytes& bytes)
|
||||
{
|
||||
std::vector<bool> bits(16);
|
||||
unsigned cursor = 0;
|
||||
bool lastBit = false;
|
||||
encodeMfm(bits, cursor, bytes, lastBit);
|
||||
return bits;
|
||||
}
|
||||
|
||||
static std::vector<bool> wrappedEncodeFm(const Bytes& bytes)
|
||||
{
|
||||
std::vector<bool> bits(16);
|
||||
unsigned cursor = 0;
|
||||
encodeFm(bits, cursor, bytes);
|
||||
return bits;
|
||||
}
|
||||
|
||||
static void testEncodeMfm(void)
|
||||
{
|
||||
assert(wrappedEncodeMfm(Bytes{ 0xa1 })
|
||||
== (std::vector<bool>{
|
||||
false, true,
|
||||
false, false,
|
||||
false, true,
|
||||
false, false,
|
||||
true, false,
|
||||
true, false,
|
||||
true, false,
|
||||
false, true
|
||||
})
|
||||
);
|
||||
|
||||
assert(wrappedEncodeMfm(Bytes{ 0xc2 })
|
||||
== (std::vector<bool>{
|
||||
false, true,
|
||||
false, true,
|
||||
false, false,
|
||||
true, false,
|
||||
true, false,
|
||||
true, false,
|
||||
false, true,
|
||||
false, false
|
||||
})
|
||||
);
|
||||
|
||||
assert(wrappedEncodeMfm(Bytes{ 0xb0 })
|
||||
== (std::vector<bool>{
|
||||
false, true,
|
||||
false, false,
|
||||
false, true,
|
||||
false, true,
|
||||
false, false,
|
||||
true, false,
|
||||
true, false,
|
||||
true, false,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
static void testEncodeFm(void)
|
||||
{
|
||||
assert(wrappedEncodeFm(Bytes{ 0x00 })
|
||||
== (std::vector<bool>{
|
||||
true, false,
|
||||
true, false,
|
||||
true, false,
|
||||
true, false,
|
||||
true, false,
|
||||
true, false,
|
||||
true, false,
|
||||
true, false
|
||||
})
|
||||
);
|
||||
|
||||
assert(wrappedEncodeFm(Bytes{ 0x81 })
|
||||
== (std::vector<bool>{
|
||||
true, true,
|
||||
true, false,
|
||||
true, false,
|
||||
true, false,
|
||||
true, false,
|
||||
true, false,
|
||||
true, false,
|
||||
true, true
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
int main(int argc, const char* argv[])
|
||||
{
|
||||
testDecode();
|
||||
testEncodeMfm();
|
||||
testEncodeFm();
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user