mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-24 11:11:02 -07:00
Compare commits
621 Commits
FluxEngine
...
firmware
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3601f9f487 | ||
|
|
7f95f6b43f | ||
|
|
b2d7ba1a65 | ||
|
|
b550bbbd08 | ||
|
|
4cbb75df60 | ||
|
|
7d8926659e | ||
|
|
37ca3f74c7 | ||
|
|
56cbf39d59 | ||
|
|
a783e7f500 | ||
|
|
2f4ac42684 | ||
|
|
ec689e100e | ||
|
|
6f0909d992 | ||
|
|
0092dec49e | ||
|
|
3447689c19 | ||
|
|
d4563fd842 | ||
|
|
d2ecec6009 | ||
|
|
26f26aec50 | ||
|
|
34dfc2767f | ||
|
|
bc3d3cabce | ||
|
|
23d80b93ae | ||
|
|
0d59d3d195 | ||
|
|
192427cf80 | ||
|
|
98e4094d70 | ||
|
|
e88b939866 | ||
|
|
aed5a02ee1 | ||
|
|
9f1e1bb2b6 | ||
|
|
15e9383d0b | ||
|
|
4ec056900c | ||
|
|
983feb59b0 | ||
|
|
8b2ce33f83 | ||
|
|
44b452b30b | ||
|
|
f60c9981b8 | ||
|
|
7c3df93580 | ||
|
|
601d7dfcf8 | ||
|
|
41cb53a550 | ||
|
|
87c13ae20c | ||
|
|
c30482af66 | ||
|
|
5f4f2f10d7 | ||
|
|
ae630a0e18 | ||
|
|
c66931cb12 | ||
|
|
fb2dbe25cd | ||
|
|
bf4831be9f | ||
|
|
0f83082cf0 | ||
|
|
fbfde604e7 | ||
|
|
5e2dfbed73 | ||
|
|
571602d3de | ||
|
|
85693f2577 | ||
|
|
60bc8ad888 | ||
|
|
9bf309eb5c | ||
|
|
eeddfa87b6 | ||
|
|
861fe2466c | ||
|
|
3a2cce78ca | ||
|
|
4e01f1de0d | ||
|
|
4f0a5e854c | ||
|
|
c669a9c808 | ||
|
|
e4d827256f | ||
|
|
1c1ad2725e | ||
|
|
d18e54c5a3 | ||
|
|
7a885e23d3 | ||
|
|
33dde3a465 | ||
|
|
8d4ac59f03 | ||
|
|
4fbfc492ce | ||
|
|
ac1fb71bc5 | ||
|
|
01d6b37b83 | ||
|
|
2284b4dce1 | ||
|
|
b92f80e6be | ||
|
|
bd5596fa30 | ||
|
|
4614b63c30 | ||
|
|
cf41b6cbb2 | ||
|
|
87f3e0e291 | ||
|
|
1997abcde6 | ||
|
|
8b761298ee | ||
|
|
df0356b841 | ||
|
|
dc158ebff4 | ||
|
|
f8192b90f4 | ||
|
|
5237049e2c | ||
|
|
9d70fb261e | ||
|
|
8370b8a743 | ||
|
|
25656d81a1 | ||
|
|
be97791428 | ||
|
|
18b683d22e | ||
|
|
34e9742f71 | ||
|
|
087eb7777e | ||
|
|
c469c5e3a1 | ||
|
|
485c29bb49 | ||
|
|
aa0cf150bd | ||
|
|
91c52e91cd | ||
|
|
a1f4014738 | ||
|
|
8a136ac4f6 | ||
|
|
ea43b3dc6a | ||
|
|
57fc787819 | ||
|
|
a0164b8de3 | ||
|
|
9df35c1814 | ||
|
|
9d2a5fee86 | ||
|
|
a6b2e932fa | ||
|
|
05aaa2634b | ||
|
|
2c98f5c542 | ||
|
|
d246fca9df | ||
|
|
c79feb405c | ||
|
|
b1145f8da3 | ||
|
|
3588d681a2 | ||
|
|
55d894ae1f | ||
|
|
0509caf432 | ||
|
|
5d1d807e78 | ||
|
|
22ba38b2e0 | ||
|
|
42f858267c | ||
|
|
5b1a3173f8 | ||
|
|
97822bd9a8 | ||
|
|
b926f5a692 | ||
|
|
191dfdf13f | ||
|
|
a100f1fe1e | ||
|
|
471ccf281c | ||
|
|
6c959be188 | ||
|
|
010887f18f | ||
|
|
e4b5e4c502 | ||
|
|
2de3b4f92e | ||
|
|
225a93330d | ||
|
|
41b36649a9 | ||
|
|
55c26ab1c4 | ||
|
|
8b1e60a1fd | ||
|
|
ed0f38748b | ||
|
|
7d75a720ca | ||
|
|
5a38db166f | ||
|
|
3c9fb79263 | ||
|
|
98d5a2dad9 | ||
|
|
4ab8b4984d | ||
|
|
f741ad058e | ||
|
|
2512a4fc32 | ||
|
|
5554d5e608 | ||
|
|
48d5ed2ff9 | ||
|
|
2632668d0e | ||
|
|
f46e444aa2 | ||
|
|
1149ad86a2 | ||
|
|
e1398d98b0 | ||
|
|
8133e2b7aa | ||
|
|
ebe678b18b | ||
|
|
509217606c | ||
|
|
6fb694669c | ||
|
|
5a63172a86 | ||
|
|
93dcc7e242 | ||
|
|
243eea33e9 | ||
|
|
38a8367f62 | ||
|
|
a02953cccc | ||
|
|
f13f96967e | ||
|
|
f7c31281e0 | ||
|
|
ac34a43d9b | ||
|
|
c8d0950979 | ||
|
|
a4ff59eccb | ||
|
|
c3a50f9442 | ||
|
|
57e81ee72e | ||
|
|
05df0a37b1 | ||
|
|
25f2c3a8c1 | ||
|
|
c3aa12db78 | ||
|
|
a3bd7cc644 | ||
|
|
5a186b6960 | ||
|
|
639588fa68 | ||
|
|
f9510c54b2 | ||
|
|
3a8ddf8025 | ||
| a2801ea88c | |||
|
|
c2aae7ee18 | ||
|
|
9d0804eff4 | ||
|
|
6ff84b3693 | ||
|
|
b641e0282b | ||
|
|
37a467cabc | ||
|
|
e01a7110ac | ||
|
|
5dad5de548 | ||
|
|
295325a20b | ||
|
|
df0a9bac96 | ||
|
|
cf9cef6f87 | ||
|
|
f92814b24b | ||
|
|
331b59cd1e | ||
|
|
ed6d211aff | ||
|
|
a8f1469d36 | ||
|
|
74cb332706 | ||
|
|
89165369b1 | ||
|
|
a54e3d33a6 | ||
|
|
0f17984f41 | ||
|
|
6527ceb913 | ||
|
|
64a57ba837 | ||
|
|
74da9330f8 | ||
|
|
4fa1dd6860 | ||
|
|
e55effc9ca | ||
|
|
924b862f7c | ||
|
|
5f077762d5 | ||
|
|
1b0ec50711 | ||
|
|
22f320f1c4 | ||
|
|
9949476584 | ||
|
|
1b5b170557 | ||
|
|
925a3a4bdb | ||
|
|
720fe9f95f | ||
|
|
7c4f8e1443 | ||
|
|
79d24dff46 | ||
|
|
928435a31d | ||
|
|
26ac92eaa3 | ||
|
|
2974c08b08 | ||
|
|
5a7b0b3050 | ||
|
|
cc2d9bbdd1 | ||
|
|
e912152784 | ||
|
|
d00681f623 | ||
|
|
52942c3d2a | ||
|
|
dedabdd8d8 | ||
|
|
3061499860 | ||
|
|
20f18755ed | ||
|
|
333f2aba54 | ||
|
|
1cb673ed80 | ||
|
|
57e0bc784a | ||
|
|
425afa93da | ||
|
|
259b2cebc7 | ||
|
|
06589826c8 | ||
|
|
2245cd982a | ||
|
|
065b50769f | ||
|
|
d1e99852bc | ||
|
|
bf8f6ae687 | ||
|
|
4ad6805ea1 | ||
|
|
4f4e3f0b89 | ||
|
|
b51f2c1ec8 | ||
|
|
1bec06fd75 | ||
|
|
451d2e2d1d | ||
|
|
9cee12f9f4 | ||
|
|
f5d6011a77 | ||
|
|
64b2ff19ea | ||
|
|
9c17a64773 | ||
|
|
69c877ff66 | ||
|
|
ac557ffedc | ||
|
|
b1e41bc583 | ||
|
|
a144395ec9 | ||
|
|
0cf9d05489 | ||
|
|
0e6c0a41d0 | ||
|
|
8a83652d08 | ||
|
|
91ee72a8d6 | ||
|
|
91b1c8c13c | ||
|
|
26effeabe6 | ||
|
|
611c9740ed | ||
|
|
2a048c3228 | ||
|
|
f4fd83d999 | ||
|
|
cf68585808 | ||
|
|
9f9e926cff | ||
|
|
9dc0dd75fd | ||
|
|
9f285710f8 | ||
|
|
ee1c448327 | ||
|
|
e85bf1713e | ||
|
|
7341c71277 | ||
|
|
d579863311 | ||
|
|
c79cfc19aa | ||
|
|
997a6be267 | ||
|
|
762bb3006d | ||
|
|
07f2bd8cab | ||
|
|
daf83db9b3 | ||
|
|
55c6e19af4 | ||
|
|
9cadc94c5a | ||
|
|
cacdf9ef56 | ||
|
|
a3042fc6c0 | ||
|
|
3efd492525 | ||
|
|
55a5cbc356 | ||
|
|
2887b024ab | ||
|
|
917303edb9 | ||
|
|
c712c15a30 | ||
|
|
0c541db8e0 | ||
|
|
603b1520d7 | ||
|
|
c7eb8ad5c8 | ||
|
|
0b285aa7f4 | ||
|
|
e8665bd00c | ||
|
|
fb4eaa4332 | ||
|
|
874a9eae76 | ||
|
|
8230520956 | ||
|
|
66da9675f1 | ||
|
|
61ff48c005 | ||
|
|
5fc8a1e52a | ||
|
|
df1ac74069 | ||
|
|
91f718bf38 | ||
|
|
46e987e393 | ||
|
|
a59b4f7be7 | ||
|
|
ca66e3c35c | ||
|
|
31e2ad8cba | ||
|
|
320f32895a | ||
|
|
d4db131d3c | ||
|
|
27c2c9045e | ||
|
|
f97b7c7d62 | ||
|
|
9eb33d31ac | ||
|
|
6dd84d6fc2 | ||
|
|
daddd60581 | ||
|
|
e832723ee4 | ||
|
|
35f4a63c0e | ||
|
|
28478ea4ac | ||
|
|
0f93a68694 | ||
|
|
1a2d5d13b3 | ||
|
|
5f2894fc5b | ||
|
|
66cb39dce2 | ||
|
|
d44c871c54 | ||
|
|
dff0378ba8 | ||
|
|
4f7b1b7140 | ||
|
|
662514304b | ||
|
|
0913e9e0c0 | ||
|
|
d403733627 | ||
|
|
fae5b439d0 | ||
|
|
bc66de6d85 | ||
|
|
57e598156c | ||
|
|
b570e44ee4 | ||
|
|
b115d0b55b | ||
|
|
03fc1419de | ||
|
|
a833aa0a00 | ||
|
|
52332b04ac | ||
|
|
529488cab0 | ||
|
|
b2429a7ca3 | ||
|
|
0bce12d3b4 | ||
|
|
75f557cb18 | ||
|
|
035dd1fad1 | ||
|
|
d2df79a665 | ||
|
|
103e0a13bb | ||
|
|
d1b5eec84a | ||
|
|
6b1e6b31ed | ||
|
|
f6f6db913e | ||
|
|
ec0a6416fd | ||
|
|
1787402be9 | ||
|
|
5f6d99f138 | ||
|
|
d1e2b0d1f8 | ||
|
|
c2c51bbe33 | ||
|
|
bb806e3853 | ||
|
|
a11d0e75c8 | ||
|
|
5406ff0ea3 | ||
|
|
c88317b44a | ||
|
|
6898062d66 | ||
|
|
6e1f264e6a | ||
|
|
082be14232 | ||
|
|
231aa44d03 | ||
|
|
cdb12f35d4 | ||
|
|
e831ee8b44 | ||
|
|
40e9a6082f | ||
|
|
53cec292d0 | ||
|
|
3f85309ee5 | ||
|
|
70944f8521 | ||
|
|
2ab00c42ff | ||
|
|
a572742caa | ||
|
|
400e5f8580 | ||
|
|
74f0fd89b6 | ||
|
|
09f9bea7a2 | ||
|
|
8bffb38117 | ||
|
|
eb5d545c35 | ||
|
|
a79a545730 | ||
|
|
3863dab944 | ||
|
|
e53b7ecd8b | ||
|
|
7d88673ed5 | ||
|
|
41f2da71e4 | ||
|
|
cb4ee0fd74 | ||
|
|
088381a5a6 | ||
|
|
629af2a697 | ||
|
|
884edfd497 | ||
|
|
83dd9e462e | ||
|
|
70a6dfd98a | ||
|
|
7f5d96382b | ||
|
|
fd4d1c4bb7 | ||
|
|
7eaf3de572 | ||
|
|
4b608de3fb | ||
|
|
b47e6e852b | ||
|
|
a8a8ce4a36 | ||
|
|
c61376d5a1 | ||
|
|
d3a5bb08d3 | ||
|
|
f1506d0dbd | ||
|
|
15e6d4959e | ||
|
|
41216fd1cd | ||
|
|
b8786866db | ||
|
|
82bd1bead4 | ||
|
|
6e2bdcad79 | ||
|
|
ef3c9f3d03 | ||
|
|
5427f24df2 | ||
|
|
b374340303 | ||
|
|
c78ed2c6ad | ||
|
|
3b02bc8cf1 | ||
|
|
c7e48a7e76 | ||
|
|
77d125c03d | ||
|
|
8aa52aeefd | ||
|
|
0bab038454 | ||
|
|
6c3b49f4d0 | ||
|
|
03dd689f17 | ||
|
|
c375c948c0 | ||
|
|
cbcf457ce3 | ||
|
|
4855f825e2 | ||
|
|
85bc1637f2 | ||
|
|
73398b83a9 | ||
|
|
2727e66d40 | ||
|
|
8b6be5a501 | ||
|
|
4fee29307c | ||
|
|
35f8249c67 | ||
|
|
d1467a14b8 | ||
|
|
3e6b9eb74d | ||
|
|
ce2e8fb4b5 | ||
|
|
7eaa75c05d | ||
|
|
e86de4483a | ||
|
|
203a74713f | ||
|
|
59ed2a6793 | ||
|
|
a03283ce64 | ||
|
|
984cdaeb03 | ||
|
|
a1ed4a9171 | ||
|
|
93caf8e549 | ||
|
|
3841942153 | ||
|
|
5706877b67 | ||
|
|
d60900262b | ||
|
|
54ea34400b | ||
|
|
db2ab8841a | ||
|
|
adba93ae0a | ||
|
|
98587d04a7 | ||
|
|
0051b64648 | ||
|
|
603009ba15 | ||
|
|
adb9809692 | ||
|
|
06eb10d2a0 | ||
|
|
2244299bd9 | ||
|
|
6ca06ecafb | ||
|
|
9a5958f80b | ||
|
|
2b53ac057c | ||
|
|
5deba8af41 | ||
|
|
3c54a663b8 | ||
|
|
1fd65452c4 | ||
|
|
30646ccb07 | ||
|
|
5be7249a30 | ||
|
|
067af18103 | ||
|
|
8dbd2a72a7 | ||
|
|
c29e131a3b | ||
|
|
a9e30c1e49 | ||
|
|
972c8c6b61 | ||
|
|
2007ff7546 | ||
|
|
64694580cd | ||
|
|
deaab94494 | ||
|
|
1509e1f89d | ||
|
|
29e1ddc2ff | ||
|
|
1fe6434563 | ||
|
|
0367b7e77d | ||
|
|
e6da85bf64 | ||
|
|
cd19fcdadd | ||
|
|
1954f02cfb | ||
|
|
39b23200b0 | ||
|
|
0644d6d965 | ||
|
|
a075694d8e | ||
|
|
b1ea5a9a35 | ||
|
|
00087cbb6b | ||
|
|
1b48ea20c4 | ||
|
|
3d0f019fc4 | ||
|
|
a08bfc183f | ||
|
|
c5aef9b051 | ||
|
|
fc2655ecd6 | ||
|
|
a737c723d3 | ||
|
|
37aa8b62b0 | ||
|
|
a401173f6d | ||
|
|
ce76dc4279 | ||
|
|
1025bd857b | ||
|
|
025802b2d0 | ||
|
|
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 | ||
|
|
ebcb9c4bb0 | ||
|
|
2520834b18 | ||
|
|
a1f3087046 | ||
|
|
e9670e205e | ||
|
|
658e2b7295 | ||
|
|
7b4a8d6de2 | ||
|
|
e8f7b51aef | ||
|
|
9d6bc57a5f | ||
|
|
73766f92b4 | ||
|
|
80badf3b54 | ||
|
|
116529f85a | ||
|
|
5a2b2bc07a | ||
|
|
41070395c0 | ||
|
|
4304d1eede | ||
|
|
46f1b0aef4 | ||
|
|
9923d67a7c | ||
|
|
99335a84fd | ||
|
|
c266779433 | ||
|
|
bdcc12cd53 | ||
|
|
7988d0fe24 | ||
|
|
27f5c294b1 | ||
|
|
b9a53e0d1c | ||
|
|
f8b6d5e6fb | ||
|
|
04ff31c348 | ||
|
|
77b4aebd1b | ||
|
|
4056364300 | ||
|
|
60bfe050d3 | ||
|
|
28d0ce765e | ||
|
|
4954d33307 | ||
|
|
55f3354287 | ||
|
|
d6ae373fa8 | ||
|
|
a626d5f9a0 | ||
|
|
29db67528d | ||
|
|
31d7477c6a | ||
|
|
56af9eaf18 | ||
|
|
5de0636fe7 | ||
|
|
f9117b8d11 | ||
|
|
10d385375f | ||
|
|
2f72c3f8f0 | ||
|
|
54edff9b94 | ||
|
|
112377f885 | ||
|
|
87e29fc386 | ||
|
|
b1db5c48b1 | ||
|
|
38fab7edcb | ||
|
|
d8172154c3 | ||
|
|
eb924780ab |
@@ -1,41 +0,0 @@
|
||||
version: '{branch}.{build}'
|
||||
clone_depth: 1
|
||||
skip_tags: true
|
||||
|
||||
environment:
|
||||
MSYSTEM: MINGW32
|
||||
|
||||
init:
|
||||
- git config --global core.autocrlf input
|
||||
|
||||
install:
|
||||
- set PATH=c:\msys64\mingw32\bin;c:\msys64\usr\bin;c:\msys64\bin;%PATH%
|
||||
- echo %PATH%
|
||||
- pacman -S --noconfirm --needed make ninja mingw-w64-i686-libusb mingw-w64-i686-sqlite3 mingw-w64-i686-zlib mingw-w64-i686-gcc zip
|
||||
|
||||
build_script:
|
||||
- make
|
||||
- zip -9 fluxengine.zip fluxengine.exe brother120tool.exe
|
||||
|
||||
artifacts:
|
||||
- path: fluxengine.zip
|
||||
name: fluxengine.zip
|
||||
|
||||
deploy:
|
||||
release: FluxEngine Windows client version $(APPVEYOR_BUILD_NUMBER)
|
||||
description: >
|
||||
This is an automatically built version of the FluxEngine Windows client
|
||||
which is generated whenever a significant checkin has happened. It's had
|
||||
no testing whatsoever.
|
||||
|
||||
To use, download it, put it somewhere, and then run it from a cmd window
|
||||
or other command line shell.
|
||||
provider: GitHub
|
||||
auth_token:
|
||||
secure: dfJjj7fWCoDUz+Ni11OcNPB/U3TNJFwNA2AsL++ChFjniUsZLlC6SDWHiL/t4FZo
|
||||
artifact: fluxengine.zip
|
||||
draft: false
|
||||
prerelease: false
|
||||
on:
|
||||
branch: master
|
||||
|
||||
54
.github/workflows/ccpp.yml
vendored
Normal file
54
.github/workflows/ccpp.yml
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
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 update && sudo apt install libusb-1.0-0-dev libsqlite3-dev ninja-build protobuf-compiler
|
||||
- name: make
|
||||
run: make
|
||||
|
||||
build-macos:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 1
|
||||
- name: brew
|
||||
run: brew install sqlite pkg-config libusb ninja protobuf
|
||||
- name: make
|
||||
run: make
|
||||
|
||||
build-windows:
|
||||
runs-on: windows-latest
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
steps:
|
||||
- uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
update: true
|
||||
msystem: MINGW32
|
||||
install: >-
|
||||
make
|
||||
ninja
|
||||
mingw-w64-i686-libusb
|
||||
mingw-w64-i686-sqlite3
|
||||
mingw-w64-i686-zlib
|
||||
mingw-w64-i686-gcc
|
||||
zip
|
||||
mingw-w64-i686-protobuf
|
||||
vim
|
||||
- uses: actions/checkout@v1
|
||||
with:
|
||||
fetch-depth: 1
|
||||
- name: build
|
||||
run: |
|
||||
make
|
||||
|
||||
63
.github/workflows/release.yml
vendored
Normal file
63
.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
name: Autorelease
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "master"
|
||||
|
||||
jobs:
|
||||
dev-release:
|
||||
runs-on: windows-latest
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
steps:
|
||||
- uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
update: true
|
||||
msystem: MINGW32
|
||||
install: >-
|
||||
make
|
||||
ninja
|
||||
mingw-w64-i686-libusb
|
||||
mingw-w64-i686-sqlite3
|
||||
mingw-w64-i686-zlib
|
||||
mingw-w64-i686-gcc
|
||||
zip
|
||||
mingw-w64-i686-protobuf
|
||||
vim
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 1
|
||||
- name: build
|
||||
run: |
|
||||
make
|
||||
- name: zip
|
||||
run: |
|
||||
zip -9 fluxengine.zip fluxengine.exe brother120tool.exe brother240tool.exe FluxEngine.cydsn/CortexM3/ARM_GCC_541/Release/FluxEngine.hex
|
||||
- name: date
|
||||
run: |
|
||||
echo "RELEASE_DATE=$(date --rfc-3339=date)" >> ${GITHUB_ENV}
|
||||
- name: tag
|
||||
uses: EndBug/latest-tag@latest
|
||||
with:
|
||||
tag-name: dev
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: delete-old-assets
|
||||
uses: mknejp/delete-release-assets@v1
|
||||
with:
|
||||
token: ${{ github.token }}
|
||||
tag: dev
|
||||
assets: |
|
||||
fluxengine.zip
|
||||
fail-if-no-assets: false
|
||||
- name: release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
name: Development build ${{ env.RELEASE_DATE }}
|
||||
files: |
|
||||
fluxengine.zip
|
||||
tag_name: dev
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -3,6 +3,10 @@ streams
|
||||
.*\.flux
|
||||
.*\.img
|
||||
.*\.raw
|
||||
.*\.orig
|
||||
.vscode
|
||||
remote
|
||||
FluxEngine.cydsn/CortexM3
|
||||
FluxEngine.cydsn/Generated_Source
|
||||
FluxEngine.cydsn/codegentemp
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
||||
4626
FluxEngine.cydsn/CortexM3/ARM_GCC_541/Release/FluxEngine.hex
Normal file
4626
FluxEngine.cydsn/CortexM3/ARM_GCC_541/Release/FluxEngine.hex
Normal file
File diff suppressed because it is too large
Load Diff
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="30" />
|
||||
<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="30" />
|
||||
<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" />
|
||||
@@ -390,7 +604,7 @@
|
||||
<Data key="check_tolerance" value="True" />
|
||||
<Data key="clock_version" value="v1" />
|
||||
<Data key="derive_type" value="BUILTIN" />
|
||||
<Data key="desired_freq" value="64" />
|
||||
<Data key="desired_freq" value="48" />
|
||||
<Data key="desired_unit" value="6" />
|
||||
<Data key="divider" value="0" />
|
||||
<Data key="domain" value="0" />
|
||||
@@ -600,7 +814,7 @@
|
||||
</Group>
|
||||
<Group key="Component">
|
||||
<Group key="v1">
|
||||
<Data key="cy_boot" value="cy_boot_v5_80" />
|
||||
<Data key="cy_boot" value="cy_boot_v6_10" />
|
||||
<Data key="Em_EEPROM_Dynamic" value="Em_EEPROM_Dynamic_v2_20" />
|
||||
<Data key="LIN_Dynamic" value="LIN_Dynamic_v5_0" />
|
||||
</Group>
|
||||
@@ -609,45 +823,60 @@
|
||||
<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>
|
||||
<Group key="Pin">
|
||||
<Data key="3e1862bb-be82-47b0-9549-7ebfe76b6f7b" value="Pin_2" />
|
||||
<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" />
|
||||
<Data key="472f8fdb-f772-44fb-8897-cc690694237b" value="WDATA" />
|
||||
<Data key="736cb12b-c863-43d4-a8f0-42f06023f8b5" value="SIDE1" />
|
||||
<Data key="4249c923-fcff-453b-8629-bec6fddd00c1" value="STEP" />
|
||||
<Data key="27315b0e-6a8c-4b7f-be77-73ab434fa803" value="Pin_1" />
|
||||
<Data key="1425177d-0d0e-4468-8bcc-e638e5509a9b" value="UartRx" />
|
||||
<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="e16b5ef8-00d3-40a4-bc1c-194983c8eb3d" value="LOW_CURRENT" />
|
||||
<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" />
|
||||
@@ -3737,6 +3966,11 @@
|
||||
</Group>
|
||||
</Group>
|
||||
<Group key="Pin2">
|
||||
<Group key="3e1862bb-be82-47b0-9549-7ebfe76b6f7b">
|
||||
<Group key="0">
|
||||
<Data key="Port Format" value="0,6" />
|
||||
</Group>
|
||||
</Group>
|
||||
<Group key="4a398466-709f-4228-9500-96178658e13e">
|
||||
<Group key="0">
|
||||
<Data key="Port Format" value="1,5" />
|
||||
@@ -3752,6 +3986,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" />
|
||||
@@ -3833,6 +4072,11 @@
|
||||
<Data key="Port Format" value="1,0" />
|
||||
</Group>
|
||||
</Group>
|
||||
<Group key="27315b0e-6a8c-4b7f-be77-73ab434fa803">
|
||||
<Group key="0">
|
||||
<Data key="Port Format" value="0,7" />
|
||||
</Group>
|
||||
</Group>
|
||||
<Group key="1425177d-0d0e-4468-8bcc-e638e5509a9b">
|
||||
<Group key="0">
|
||||
<Data key="Port Format" value="12,6" />
|
||||
@@ -3859,6 +4103,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" />
|
||||
@@ -3892,9 +4162,14 @@
|
||||
<Data key="Port Format" value="12,3" />
|
||||
</Group>
|
||||
</Group>
|
||||
<Group key="e16b5ef8-00d3-40a4-bc1c-194983c8eb3d">
|
||||
<Group key="0">
|
||||
<Data key="Port Format" value="3,2" />
|
||||
</Group>
|
||||
</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 +4187,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">
|
||||
@@ -3934,7 +4214,7 @@
|
||||
</Group>
|
||||
<Group key="System3">
|
||||
<Data key="CYDEV_CONFIG_FASTBOOT_ENABLED" value="True" />
|
||||
<Data key="CYDEV_CONFIG_UNUSED_IO" value="AllowButWarn" />
|
||||
<Data key="CYDEV_CONFIG_UNUSED_IO" value="Disallowed" />
|
||||
<Data key="CYDEV_CONFIGURATION_ECC" value="True" />
|
||||
<Data key="CYDEV_CONFIGURATION_MODE" value="COMPRESSED" />
|
||||
<Data key="CYDEV_DEBUGGING_DPS" value="Disable" />
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
83
FluxEngine.cydsn/Sampler/Sampler.v
Normal file
83
FluxEngine.cydsn/Sampler/Sampler.v
Normal file
@@ -0,0 +1,83 @@
|
||||
|
||||
//`#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 12/11/2019 at 21:18
|
||||
// Component: Sampler
|
||||
module Sampler (
|
||||
output [2:0] debug_state,
|
||||
output reg [7:0] opcode,
|
||||
output reg req,
|
||||
input clock,
|
||||
input index,
|
||||
input rdata,
|
||||
input reset,
|
||||
input sampleclock
|
||||
);
|
||||
|
||||
//`#start body` -- edit after this line, do not edit this line
|
||||
|
||||
// NOTE: Reset pulse is used in both clock domains, and must be long enough
|
||||
// to be detected in both.
|
||||
|
||||
reg [5:0] counter;
|
||||
|
||||
reg index_q;
|
||||
reg rdata_q;
|
||||
|
||||
reg index_edge;
|
||||
reg rdata_edge;
|
||||
|
||||
reg req_toggle;
|
||||
|
||||
always @(posedge sampleclock)
|
||||
begin
|
||||
if (reset)
|
||||
begin
|
||||
index_edge <= 0;
|
||||
rdata_edge <= 0;
|
||||
index_q <= 0;
|
||||
rdata_q <= 0;
|
||||
counter <= 0;
|
||||
req_toggle <= 0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
/* Both index and rdata are active high -- positive-going edges
|
||||
* indicate the start of an index pulse and read pulse, respectively.
|
||||
*/
|
||||
|
||||
index_edge <= index && !index_q;
|
||||
index_q <= index;
|
||||
|
||||
rdata_edge <= rdata && !rdata_q;
|
||||
rdata_q <= rdata;
|
||||
|
||||
if (rdata_edge || index_edge || (counter == 6'h3f)) begin
|
||||
opcode <= { rdata_edge, index_edge, counter };
|
||||
req_toggle <= ~req_toggle;
|
||||
counter <= 1; /* remember to count this tick */
|
||||
end else begin
|
||||
counter <= counter + 1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
reg req_toggle_q;
|
||||
|
||||
always @(posedge clock)
|
||||
begin
|
||||
if (reset) begin
|
||||
req_toggle_q <= 0;
|
||||
req <= 0;
|
||||
end else begin
|
||||
req_toggle_q <= req_toggle;
|
||||
req <= (req_toggle != req_toggle_q);
|
||||
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
|
||||
Binary file not shown.
91
FluxEngine.cydsn/Sequencer/Sequencer.v
Normal file
91
FluxEngine.cydsn/Sequencer/Sequencer.v
Normal file
@@ -0,0 +1,91 @@
|
||||
|
||||
//`#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_WRITING = 1;
|
||||
localparam STATE_WAITING = 2;
|
||||
|
||||
reg [1:0] state;
|
||||
reg [5:0] countdown;
|
||||
reg pulsepending;
|
||||
|
||||
assign req = (!reset && (state == STATE_LOAD));
|
||||
assign wdata = (!reset && (state == STATE_WAITING) && (countdown == 0) && pulsepending);
|
||||
assign debug_state = 0;
|
||||
|
||||
reg olddataclock;
|
||||
wire dataclocked;
|
||||
always @(posedge clock) olddataclock <= dataclock;
|
||||
assign dataclocked = !olddataclock && dataclock;
|
||||
|
||||
reg oldsampleclock;
|
||||
reg sampleclocked;
|
||||
|
||||
always @(posedge clock)
|
||||
begin
|
||||
if (reset)
|
||||
begin
|
||||
state <= STATE_LOAD;
|
||||
countdown <= 0;
|
||||
pulsepending <= 0;
|
||||
oldsampleclock <= 0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if (!oldsampleclock && sampleclock)
|
||||
sampleclocked <= 1;
|
||||
oldsampleclock <= sampleclock;
|
||||
|
||||
case (state)
|
||||
STATE_LOAD:
|
||||
begin
|
||||
/* A posedge on dataclocked indicates that another opcode has
|
||||
* arrived. */
|
||||
if (dataclocked)
|
||||
begin
|
||||
pulsepending <= opcode[7];
|
||||
countdown <= opcode[5:0] - 1; /* compensate for extra tick in state machine */
|
||||
|
||||
state <= STATE_WRITING;
|
||||
end
|
||||
end
|
||||
|
||||
STATE_WRITING:
|
||||
begin
|
||||
if (sampleclocked)
|
||||
begin
|
||||
if (countdown == 0)
|
||||
state <= STATE_WAITING;
|
||||
else
|
||||
countdown <= countdown - 1;
|
||||
sampleclocked <= 0;
|
||||
end
|
||||
end
|
||||
|
||||
STATE_WAITING:
|
||||
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.
@@ -5,7 +5,6 @@
|
||||
#include <setjmp.h>
|
||||
#include "project.h"
|
||||
#include "../protocol.h"
|
||||
#include "../lib/common/crunch.h"
|
||||
|
||||
#define MOTOR_ON_TIME 5000 /* milliseconds */
|
||||
#define STEP_INTERVAL_TIME 6 /* ms */
|
||||
@@ -14,19 +13,26 @@
|
||||
#define DISKSTATUS_WPT 1
|
||||
#define DISKSTATUS_DSKCHG 2
|
||||
|
||||
#define STEP_TOWARDS0 1
|
||||
#define STEP_AWAYFROM0 0
|
||||
#define STEP_TOWARDS0 0
|
||||
#define STEP_AWAYFROM0 1
|
||||
|
||||
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;
|
||||
/* Duration in ms. 0 causes every pulse to be an index pulse. Durations since
|
||||
* last pulse greater than this value imply sector pulse. Otherwise is an index
|
||||
* pulse. */
|
||||
static volatile uint32_t hardsec_index_threshold = 0;
|
||||
|
||||
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()));
|
||||
@@ -41,21 +47,67 @@ 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;
|
||||
}
|
||||
|
||||
CY_ISR(index_irq_cb)
|
||||
{
|
||||
index_irq = true;
|
||||
/* Hard sectored media has sector pulses at the beginning of every sector
|
||||
* and the index pulse is an extra pulse in the middle of the last sector.
|
||||
* When the extra pulse is seen, the next sector pulse is also the start of
|
||||
* the track. */
|
||||
static bool hardsec_index_irq_primed = false;
|
||||
static uint32_t hardsec_last_pulse_time = 0;
|
||||
uint32_t index_pulse_duration = clock - hardsec_last_pulse_time;
|
||||
|
||||
if (!hardsec_index_threshold)
|
||||
{
|
||||
index_irq = true;
|
||||
hardsec_index_irq_primed = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* It's only an index pulse if the previous pulse is less than
|
||||
* the threshold.
|
||||
*/
|
||||
index_irq = (index_pulse_duration <= hardsec_index_threshold) ?
|
||||
hardsec_index_irq_primed : false;
|
||||
|
||||
if (index_irq)
|
||||
hardsec_index_irq_primed = false;
|
||||
else
|
||||
hardsec_index_irq_primed =
|
||||
index_pulse_duration <= hardsec_index_threshold;
|
||||
|
||||
hardsec_last_pulse_time = clock;
|
||||
}
|
||||
|
||||
/* Stop writing the instant the index pulse comes along; it may take a few
|
||||
* moments for the main code to notice the pulse, and we don't want to overwrite
|
||||
* the beginning of the track. */
|
||||
ERASE_REG_Write(0);
|
||||
if (index_irq)
|
||||
ERASE_REG_Write(0);
|
||||
}
|
||||
|
||||
CY_ISR(capture_dma_finished_irq_cb)
|
||||
@@ -85,10 +137,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,12 +166,28 @@ 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)
|
||||
;
|
||||
}
|
||||
|
||||
static void wait_until_readable(int ep)
|
||||
{
|
||||
while (USBFS_GetEPState(ep) != USBFS_OUT_BUFFER_FULL)
|
||||
;
|
||||
}
|
||||
|
||||
static void send_reply(struct any_frame* f)
|
||||
{
|
||||
print("reply 0x%02x", f->f.type);
|
||||
@@ -122,9 +205,15 @@ static void send_error(int code)
|
||||
/* buffer must be big enough for a frame */
|
||||
static int usb_read(int ep, uint8_t buffer[FRAME_SIZE])
|
||||
{
|
||||
if (USBFS_GetEPState(ep) != USBFS_OUT_BUFFER_FULL)
|
||||
{
|
||||
USBFS_EnableOutEP(ep);
|
||||
wait_until_readable(ep);
|
||||
}
|
||||
|
||||
int length = USBFS_GetEPCount(ep);
|
||||
USBFS_ReadOutEP(ep, buffer, length);
|
||||
while (USBFS_GetEPState(ep) == USBFS_OUT_BUFFER_FULL)
|
||||
while (USBFS_GetEPState(ep) != USBFS_OUT_BUFFER_EMPTY)
|
||||
;
|
||||
return length;
|
||||
}
|
||||
@@ -138,25 +227,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 +267,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)
|
||||
{
|
||||
@@ -186,6 +282,7 @@ static void seek_to(int track)
|
||||
CyWdtClear();
|
||||
}
|
||||
CyDelay(STEP_SETTLING_TIME);
|
||||
TK43_REG_Write(track < 43); /* high if 0..42, low if 43 or up */
|
||||
print("finished seek");
|
||||
}
|
||||
|
||||
@@ -204,30 +301,48 @@ static void cmd_recalibrate(void)
|
||||
send_reply(&r);
|
||||
}
|
||||
|
||||
static void cmd_measure_speed(struct any_frame* f)
|
||||
static void cmd_measure_speed(struct measurespeed_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 > 1500)
|
||||
{
|
||||
elapsed = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (elapsed != 0)
|
||||
{
|
||||
int target_pulse_count = f->hard_sector_count + 1;
|
||||
start_clock = clock;
|
||||
for (int x=0; x<target_pulse_count; x++)
|
||||
{
|
||||
index_irq = false;
|
||||
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 +351,44 @@ 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++)
|
||||
{
|
||||
usb_read(FLUXENGINE_DATA_OUT_EP_NUM, buffer);
|
||||
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,8 +397,8 @@ static void deinit_dma(void)
|
||||
|
||||
static void init_capture_dma(void)
|
||||
{
|
||||
dma_channel = CAPTURE_DMA_DmaInitialize(
|
||||
2 /* bytes */,
|
||||
dma_channel = SAMPLER_DMA_DmaInitialize(
|
||||
1 /* bytes */,
|
||||
true /* request per burst */,
|
||||
HI16(CYDEV_PERIPH_BASE),
|
||||
HI16(CYDEV_SRAM_BASE));
|
||||
@@ -264,49 +412,45 @@ 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]));
|
||||
}
|
||||
}
|
||||
|
||||
static void cmd_read(struct read_frame* f)
|
||||
{
|
||||
SIDE_REG_Write(f->side);
|
||||
seek_to(current_track);
|
||||
|
||||
SIDE_REG_Write(f->side);
|
||||
STEP_REG_Write(f->side); /* for drives which multiplex SIDE and DIR */
|
||||
/* 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;
|
||||
|
||||
crunch_state_t cs = {};
|
||||
cs.outputptr = usb_buffer;
|
||||
cs.outputlen = BUFFER_SIZE;
|
||||
if (f->synced)
|
||||
{
|
||||
hardsec_index_threshold = f->hardsec_threshold_ms;
|
||||
index_irq = false;
|
||||
while (!index_irq)
|
||||
;
|
||||
index_irq = false;
|
||||
hardsec_index_threshold = 0;
|
||||
}
|
||||
|
||||
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 +458,68 @@ 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. */
|
||||
|
||||
wait_until_writeable(FLUXENGINE_DATA_IN_EP_NUM);
|
||||
USBFS_LoadInEP(FLUXENGINE_DATA_IN_EP_NUM, dma_buffer[dma_reading_from_td], BUFFER_SIZE);
|
||||
count++;
|
||||
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);
|
||||
/* Terminate the transfer (all transfers are an exact number of fragments). */
|
||||
wait_until_writeable(FLUXENGINE_DATA_IN_EP_NUM);
|
||||
unsigned zz = cs.outputlen;
|
||||
if (cs.outputlen != BUFFER_SIZE)
|
||||
USBFS_LoadInEP(FLUXENGINE_DATA_IN_EP_NUM, usb_buffer, BUFFER_SIZE-cs.outputlen);
|
||||
if ((cs.outputlen == BUFFER_SIZE) || (cs.outputlen == 0))
|
||||
USBFS_LoadInEP(FLUXENGINE_DATA_IN_EP_NUM, NULL, 0);
|
||||
USBFS_LoadInEP(FLUXENGINE_DATA_IN_EP_NUM, NULL, 0);
|
||||
wait_until_writeable(FLUXENGINE_DATA_IN_EP_NUM);
|
||||
deinit_dma();
|
||||
|
||||
if (dma_underrun)
|
||||
STEP_REG_Write(0);
|
||||
if (saved_dma_underrun)
|
||||
{
|
||||
print("underrun after %d packets");
|
||||
send_error(F_ERROR_UNDERRUN);
|
||||
@@ -391,7 +529,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,46 +550,47 @@ 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;
|
||||
}
|
||||
|
||||
seek_to(current_track);
|
||||
SIDE_REG_Write(f->side);
|
||||
SEQUENCER_CONTROL_Write(1); /* reset */
|
||||
STEP_REG_Write(f->side); /* for drives which multiplex SIDE and DIR */
|
||||
SEQUENCER_CONTROL_Write(1); /* put the sequencer into 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);
|
||||
|
||||
init_replay_dma();
|
||||
bool writing = false; /* to the disk */
|
||||
bool finished = false;
|
||||
int packets = f->bytes_to_write / FRAME_SIZE;
|
||||
bool finished = (packets == 0);
|
||||
int count_written = 0;
|
||||
int count_read = 0;
|
||||
dma_writing_to_td = 0;
|
||||
dma_reading_from_td = -1;
|
||||
dma_underrun = false;
|
||||
|
||||
crunch_state_t cs = {};
|
||||
cs.outputlen = BUFFER_SIZE;
|
||||
USBFS_EnableOutEP(FLUXENGINE_DATA_OUT_EP_NUM);
|
||||
|
||||
int old_reading_from_td = -1;
|
||||
for (;;)
|
||||
{
|
||||
//CyWdtClear();
|
||||
|
||||
/* Read data from USB into the buffers. */
|
||||
|
||||
if (NEXT_BUFFER(dma_writing_to_td) != dma_reading_from_td)
|
||||
@@ -459,54 +598,25 @@ static void cmd_write(struct write_frame* f)
|
||||
if (writing && (dma_underrun || index_irq))
|
||||
goto abort;
|
||||
|
||||
/* Read crunched data, if necessary. */
|
||||
|
||||
if (cs.inputlen == 0)
|
||||
uint8_t* buffer = dma_buffer[dma_writing_to_td];
|
||||
if (finished)
|
||||
{
|
||||
if (finished)
|
||||
{
|
||||
/* 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;
|
||||
cs.inputlen = BUFFER_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (USBFS_GetEPState(FLUXENGINE_DATA_OUT_EP_NUM) != USBFS_OUT_BUFFER_FULL)
|
||||
{
|
||||
if (writing && (dma_underrun || index_irq))
|
||||
goto abort;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
/* There's no more data to read, so fake some. */
|
||||
|
||||
memset(buffer, 0x3f, BUFFER_SIZE);
|
||||
}
|
||||
|
||||
/* If there *is* data waiting in the buffer, uncrunch it. */
|
||||
|
||||
if (cs.inputlen != 0)
|
||||
else
|
||||
{
|
||||
cs.outputptr = dma_buffer[dma_writing_to_td] + BUFFER_SIZE - cs.outputlen;
|
||||
uncrunch(&cs);
|
||||
if (cs.outputlen == 0)
|
||||
{
|
||||
/* Completed a DMA buffer; queue it for writing. */
|
||||
|
||||
dma_writing_to_td = NEXT_BUFFER(dma_writing_to_td);
|
||||
cs.outputlen = BUFFER_SIZE;
|
||||
}
|
||||
(void) usb_read(FLUXENGINE_DATA_OUT_EP_NUM, buffer);
|
||||
count_read++;
|
||||
|
||||
if (count_read == packets)
|
||||
finished = true;
|
||||
}
|
||||
dma_writing_to_td = NEXT_BUFFER(dma_writing_to_td);
|
||||
|
||||
/* Once all the buffers are full, start writing. */
|
||||
|
||||
/* If we have a full buffer, 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 +631,7 @@ static void cmd_write(struct write_frame* f)
|
||||
|
||||
/* Wait for the index marker. While this happens, the DMA engine
|
||||
* will prime the FIFO. */
|
||||
|
||||
hardsec_index_threshold = f->hardsec_threshold_ms;
|
||||
index_irq = false;
|
||||
while (!index_irq)
|
||||
;
|
||||
@@ -532,7 +642,7 @@ static void cmd_write(struct write_frame* f)
|
||||
SEQUENCER_CONTROL_Write(0); /* start writing! */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (writing && (dma_underrun || index_irq))
|
||||
goto abort;
|
||||
|
||||
@@ -555,31 +665,30 @@ 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);
|
||||
hardsec_index_threshold = 0;
|
||||
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)
|
||||
{
|
||||
int length = usb_read(FLUXENGINE_DATA_OUT_EP_NUM, usb_buffer);
|
||||
if (length < FRAME_SIZE)
|
||||
break;
|
||||
USBFS_EnableOutEP(FLUXENGINE_DATA_OUT_EP_NUM);
|
||||
count_read++;
|
||||
}
|
||||
(void) usb_read(FLUXENGINE_DATA_OUT_EP_NUM, usb_buffer);
|
||||
count_read++;
|
||||
}
|
||||
USBFS_DisableOutEP(FLUXENGINE_DATA_OUT_EP_NUM);
|
||||
}
|
||||
|
||||
deinit_dma();
|
||||
|
||||
STEP_REG_Write(0);
|
||||
if (dma_underrun)
|
||||
{
|
||||
print("underrun!");
|
||||
send_error(F_ERROR_UNDERRUN);
|
||||
return;
|
||||
}
|
||||
|
||||
print("success");
|
||||
DECLARE_REPLY_FRAME(struct any_frame, F_FRAME_WRITE_REPLY);
|
||||
send_reply((struct any_frame*) &r);
|
||||
}
|
||||
@@ -587,10 +696,11 @@ abort:
|
||||
static void cmd_erase(struct erase_frame* f)
|
||||
{
|
||||
SIDE_REG_Write(f->side);
|
||||
seek_to(current_track);
|
||||
seek_to(current_track);
|
||||
/* Disk is now spinning. */
|
||||
|
||||
print("start erasing");
|
||||
hardsec_index_threshold = f->hardsec_threshold_ms;
|
||||
index_irq = false;
|
||||
while (!index_irq)
|
||||
;
|
||||
@@ -599,6 +709,7 @@ static void cmd_erase(struct erase_frame* f)
|
||||
while (!index_irq)
|
||||
;
|
||||
ERASE_REG_Write(0);
|
||||
hardsec_index_threshold = 0;
|
||||
print("stop erasing");
|
||||
|
||||
DECLARE_REPLY_FRAME(struct any_frame, F_FRAME_ERASE_REPLY);
|
||||
@@ -607,17 +718,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];
|
||||
@@ -636,11 +835,15 @@ static void handle_command(void)
|
||||
break;
|
||||
|
||||
case F_FRAME_MEASURE_SPEED_CMD:
|
||||
cmd_measure_speed(f);
|
||||
cmd_measure_speed((struct measurespeed_frame*) 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,28 +865,49 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
static void detect_drives(void)
|
||||
{
|
||||
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");
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
CyGlobalIntEnable;
|
||||
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);
|
||||
USBFS_DisableOutEP(FLUXENGINE_DATA_OUT_EP_NUM);
|
||||
|
||||
detect_drives();
|
||||
CyWdtStart(CYWDT_1024_TICKS, CYWDT_LPMODE_DISABLED);
|
||||
|
||||
/* UART_PutString("GO\r"); */
|
||||
|
||||
for (;;)
|
||||
{
|
||||
CyWdtClear();
|
||||
@@ -692,23 +916,21 @@ 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())
|
||||
{
|
||||
print("Waiting for USB...");
|
||||
while (!USBFS_GetConfiguration())
|
||||
;
|
||||
CyWdtClear();
|
||||
print("USB ready");
|
||||
USBFS_EnableOutEP(FLUXENGINE_CMD_OUT_EP_NUM);
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
44
Makefile
44
Makefile
@@ -1,33 +1,57 @@
|
||||
PACKAGES = zlib sqlite3 libusb-1.0
|
||||
PACKAGES = zlib sqlite3 libusb-1.0 protobuf
|
||||
|
||||
export CFLAGS = -O3 -g --std=c++14 \
|
||||
-ffunction-sections -fdata-sections
|
||||
export LDFLAGS = -O3
|
||||
export CFLAGS = -x c++ --std=c++14 -ffunction-sections -fdata-sections
|
||||
export LDFLAGS = -pthread
|
||||
|
||||
export COPTFLAGS = -Os
|
||||
export LDOPTFLAGS = -Os
|
||||
|
||||
export CDBGFLAGS = -O0 -g
|
||||
export LDDBGFLAGS = -O0 -g
|
||||
|
||||
ifeq ($(OS), Windows_NT)
|
||||
export PROTOC = /mingw32/bin/protoc
|
||||
export CXX = /mingw32/bin/g++
|
||||
export AR = /mingw32/bin/ar rcs
|
||||
export AR = /mingw32/bin/ar rc
|
||||
export RANLIB = /mingw32/bin/ranlib
|
||||
export STRIP = /mingw32/bin/strip
|
||||
export CFLAGS += -I/mingw32/include/libusb-1.0
|
||||
export CFLAGS += -I/mingw32/include/libusb-1.0 -I/mingw32/include
|
||||
export LDFLAGS +=
|
||||
export LIBS = -static -lz -lsqlite3 -lusb-1.0
|
||||
export LIBS += -L/mingw32/lib -static -lz -lsqlite3 -lusb-1.0 -lprotobuf
|
||||
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 PROTOC = protoc
|
||||
export CXX = g++
|
||||
export AR = ar rcs
|
||||
export AR = ar rc
|
||||
export RANLIB = ranlib
|
||||
export STRIP = strip
|
||||
export CFLAGS += $(shell pkg-config --cflags $(PACKAGES))
|
||||
export LDFLAGS +=
|
||||
export LIBS = $(shell pkg-config --libs $(PACKAGES))
|
||||
export LIBS += $(shell pkg-config --libs $(PACKAGES))
|
||||
export EXTENSION =
|
||||
|
||||
ifeq ($(shell uname),Darwin)
|
||||
AR = ar rcS
|
||||
RANLIB += -c -no_warning_for_no_symbols
|
||||
endif
|
||||
|
||||
endif
|
||||
export XXD = xxd
|
||||
|
||||
CFLAGS += -Ilib -Idep/fmt -Iarch
|
||||
|
||||
export OBJDIR = .obj
|
||||
|
||||
all: .obj/build.ninja
|
||||
@ninja -f .obj/build.ninja -v
|
||||
@ninja -f .obj/build.ninja
|
||||
@if command -v cscope > /dev/null; then cscope -bRq; fi
|
||||
|
||||
clean:
|
||||
@echo CLEAN
|
||||
|
||||
94
README.md
94
README.md
@@ -4,6 +4,11 @@ FluxEngine
|
||||
(If you're reading this on GitHub, the formatting's a bit messed up. [Try the
|
||||
version on cowlark.com instead.](http://cowlark.com/fluxengine/)
|
||||
|
||||
**Breaking news!** As of 2021-05-21, the command line environment has changed
|
||||
_substantially_ (to make it more consistent and flexible, and allow some new
|
||||
backend features like multi-format IBM scheme disks, which are popular with
|
||||
CP/M). If things don't work the way you expect, please check the documentation.
|
||||
|
||||
What?
|
||||
-----
|
||||
|
||||
@@ -24,17 +29,18 @@ Don't believe me? Watch the demo reel!
|
||||
<iframe width="373" height="210" src="https://www.youtube.com/embed/m_s1iw8eW7o" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
</div>
|
||||
|
||||
**Important note.** On 2019-02-09 I did a hardware redesign and moved the pins on
|
||||
the board. Sorry for the inconvenience, but it means you don't have to modify
|
||||
the board any more to make it work. If you built the hardware prior to then,
|
||||
you'll need to adjust it.
|
||||
**New!** The FluxEngine client software now works with
|
||||
[GreaseWeazle](https://github.com/keirf/Greaseweazle/wiki) hardware. So, if you
|
||||
can't find a PSoC5 development kit, or don't want to use the Cypress Windows
|
||||
tools for programming it, you can use one of these instead. Very nearly all
|
||||
FluxEngine features are available with the GreaseWeazle and it works out-of-the
|
||||
box. See the [dedicated GreaseWeazle documentation page](doc/greaseweazle.md)
|
||||
for more information.
|
||||
|
||||
**Another important note.** On 2019-07-03 I've revamped the build process and
|
||||
the (command line) user interface. It should be much nicer now, not least in
|
||||
that there's a single client binary with all the functionality in it. The
|
||||
interface is a little different, but not much. The build process is now
|
||||
better (simpler). See [the building](doc/building.md) and
|
||||
[using](doc/using.md) pages for more details.
|
||||
**Important note.** On 2020-04-02 I changed the bytecode format (and firmware).
|
||||
Flux files will need to be upgraded with `fluxengine upgradefluxfile`. The new
|
||||
format should be more reliable and use way, way less bandwidth. Sorry for the
|
||||
inconvenience.
|
||||
|
||||
Where?
|
||||
------
|
||||
@@ -59,8 +65,15 @@ following friendly articles:
|
||||
- [Using a FluxEngine](doc/using.md) ∾ what to do with your new hardware ∾
|
||||
flux files and image files ∾ knowing what you're doing
|
||||
|
||||
- [Troubleshooting dubious disks](doc/problems.md) ∾ it's not an exact science ∾
|
||||
the sector map ∾ clock detection and the histogram
|
||||
- [Using GreaseWeazle hardware with the FluxEngine client
|
||||
software](doc/greaseweazle.md) ∾ what works ∾ what doesn't work ∾ where to
|
||||
go for help
|
||||
|
||||
- [Troubleshooting dubious disks](doc/problems.md) ∾ it's not an exact
|
||||
science ∾ the sector map ∾ clock detection and the histogram
|
||||
|
||||
- [Checking your drive](doc/driveresponse.md) ∾ you can't do that with that ∾
|
||||
measuring your drive's ability to work with exotic formats
|
||||
|
||||
Which?
|
||||
------
|
||||
@@ -77,22 +90,26 @@ people who've had it work).
|
||||
|
||||
### Old disk formats
|
||||
|
||||
| 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) | 🦖 | | |
|
||||
| [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 |
|
||||
| Format | Read? | Write? | Notes |
|
||||
|:------------------------------------------|:-----:|:------:|-------|
|
||||
| [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/1581](doc/disk-c64.md) | 🦄 | 🦄 | and probably the other 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 |
|
||||
{: .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
|
||||
@@ -106,8 +123,12 @@ at least, check the CRC so what data's there is probably good.
|
||||
| [AES Superplus / No Problem](doc/disk-aeslanier.md) | 🦖 | | hard sectors! |
|
||||
| [Durango F85](doc/disk-durangof85.md) | 🦖 | | 5.25" |
|
||||
| [DVK MX](doc/disk-mx.md) | 🦖 | | Soviet PDP-11 clone |
|
||||
| [Victor 9000](doc/disk-victor9k.md) | 🦖 | | 8-inch |
|
||||
| [Zilog MCZ](doc/disk-zilogmcz.md) | 🦖 | | 8-inch _and_ hard sectors |
|
||||
| [VDS Eco1](doc/disk-eco1.md) | 🦖 | | 8" mixed format |
|
||||
| [Micropolis](doc/disk-micropolis.md) | 🦄 | | Micropolis 100tpi drives |
|
||||
| [Northstar(doc/disk-northstar.md) | 🦖 | 🦖 | 5.25" hard sectors |
|
||||
| [TI DS990 FD1000](doc/disk-tids990.md) | 🦄 | 🦄 | 8" |
|
||||
| [Victor 9000](doc/disk-victor9k.md) | 🦖 | | 8" |
|
||||
| [Zilog MCZ](doc/disk-zilogmcz.md) | 🦖 | | 8" _and_ hard sectors |
|
||||
{: .datatable }
|
||||
|
||||
### Notes
|
||||
@@ -191,6 +212,21 @@ contributions from many other people. It is licensed under the terms of the
|
||||
BSD license. Please see the contents of the directory for the full text.
|
||||
|
||||
As an exception, `dep/emu` contains parts of the OpenBSD C library
|
||||
code, Todd Miller and William A. Rowe (and probably others). It is licensed
|
||||
code, maintained by Todd Miller and William A. Rowe (and probably others). It is licensed
|
||||
under the terms of the 3-clause BSD license. Please see the contents of the
|
||||
directory for the full text. It's been lightly modified by me.
|
||||
|
||||
As an exception, `dep/agg` contains parts of the Anti-Grain Antialiasing
|
||||
library, written by Maxim Semanarev (and others). It is licensed under the
|
||||
terms of the 3-clause BSD license. Please see the contents of the directory for
|
||||
the full text. It's been lightly modified by me.
|
||||
|
||||
As an exception, `dep/stb` contains parts of the libstb utility library,
|
||||
written by Sean T Barett (and others). It is public domain/Unlicense/MIT
|
||||
licensed, at your choice. Please see the contents of the directory for the full
|
||||
text.
|
||||
|
||||
As an exception, `dep/snowhouse` contains the snowhouse assertion library,
|
||||
taken from https://github.com/banditcpp/snowhouse. It is Boost Standard License
|
||||
1.0 licensed. Please see the contents of the directory for the full text.
|
||||
|
||||
|
||||
@@ -7,10 +7,12 @@
|
||||
|
||||
class Sector;
|
||||
class Fluxmap;
|
||||
class AesLanierDecoderProto;
|
||||
|
||||
class AesLanierDecoder : public AbstractDecoder
|
||||
{
|
||||
public:
|
||||
AesLanierDecoder(const AesLanierDecoderProto&) {}
|
||||
virtual ~AesLanierDecoder() {}
|
||||
|
||||
RecordType advanceToNextRecord();
|
||||
|
||||
4
arch/aeslanier/aeslanier.proto
Normal file
4
arch/aeslanier/aeslanier.proto
Normal file
@@ -0,0 +1,4 @@
|
||||
syntax = "proto2";
|
||||
|
||||
message AesLanierDecoderProto {}
|
||||
|
||||
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,20 +1,49 @@
|
||||
#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 AmigaDecoderProto;
|
||||
class AmigaEncoderProto;
|
||||
|
||||
class AmigaDecoder : public AbstractDecoder
|
||||
{
|
||||
public:
|
||||
AmigaDecoder(const AmigaDecoderProto&) {}
|
||||
virtual ~AmigaDecoder() {}
|
||||
|
||||
RecordType advanceToNextRecord();
|
||||
void decodeSectorRecord();
|
||||
|
||||
std::set<unsigned> requiredSectors(Track& track) const;
|
||||
};
|
||||
|
||||
class AmigaEncoder : public AbstractEncoder
|
||||
{
|
||||
public:
|
||||
AmigaEncoder(const AmigaEncoderProto& config):
|
||||
_config(config) {}
|
||||
virtual ~AmigaEncoder() {}
|
||||
|
||||
public:
|
||||
std::unique_ptr<Fluxmap> encode(int physicalTrack, int physicalSide, const SectorSet& allSectors);
|
||||
|
||||
private:
|
||||
const AmigaEncoderProto& _config;
|
||||
};
|
||||
|
||||
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
|
||||
|
||||
13
arch/amiga/amiga.proto
Normal file
13
arch/amiga/amiga.proto
Normal file
@@ -0,0 +1,13 @@
|
||||
syntax = "proto2";
|
||||
|
||||
import "lib/common.proto";
|
||||
|
||||
message AmigaDecoderProto {}
|
||||
|
||||
message AmigaEncoderProto {
|
||||
optional double clock_rate_us = 1
|
||||
[default=2.00, (help)="Encoded data clock rate."];
|
||||
optional double post_index_gap_ms = 2
|
||||
[default=0.5, (help)="Post-index gap before first sector header."];
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
@@ -73,25 +32,36 @@ AbstractDecoder::RecordType AmigaDecoder::advanceToNextRecord()
|
||||
void AmigaDecoder::decodeSectorRecord()
|
||||
{
|
||||
const auto& rawbits = readRawBits(AMIGA_RECORD_SIZE*16);
|
||||
if (rawbits.size() < (AMIGA_RECORD_SIZE*16))
|
||||
return;
|
||||
const auto& rawbytes = toBytes(rawbits).slice(0, AMIGA_RECORD_SIZE*2);
|
||||
const auto& bytes = decodeFmMfm(rawbits).slice(0, AMIGA_RECORD_SIZE);
|
||||
|
||||
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));
|
||||
_sector->data = deinterleave(ptr, 512);
|
||||
uint32_t wanteddatachecksum = amigaDeinterleave(ptr, 4).reader().read_be32();
|
||||
uint32_t gotdatachecksum = amigaChecksum(rawbytes.slice(62, 1024));
|
||||
|
||||
_sector->data.clear();
|
||||
_sector->data.writer().append(amigaDeinterleave(ptr, 512)).append(recoveryinfo);
|
||||
_sector->status = (gotdatachecksum == wanteddatachecksum) ? Sector::OK : Sector::BAD_CHECKSUM;
|
||||
}
|
||||
|
||||
std::set<unsigned> AmigaDecoder::requiredSectors(Track& track) const
|
||||
{
|
||||
static std::set<unsigned> sectors = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
|
||||
return sectors;
|
||||
}
|
||||
|
||||
|
||||
126
arch/amiga/encoder.cc
Normal file
126
arch/amiga/encoder.cc
Normal file
@@ -0,0 +1,126 @@
|
||||
#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"
|
||||
#include "arch/amiga/amiga.pb.h"
|
||||
|
||||
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())
|
||||
lastBit = bits[cursor++] = bit;
|
||||
}
|
||||
}
|
||||
|
||||
static void write_bits(std::vector<bool>& bits, unsigned& cursor, uint64_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;
|
||||
}
|
||||
}
|
||||
|
||||
static void write_bits(std::vector<bool>& bits, unsigned& cursor, const Bytes& bytes)
|
||||
{
|
||||
ByteReader br(bytes);
|
||||
BitReader bitr(br);
|
||||
|
||||
while (!bitr.eof())
|
||||
{
|
||||
if (cursor < bits.size())
|
||||
bits[cursor++] = bitr.get();
|
||||
}
|
||||
}
|
||||
|
||||
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";
|
||||
|
||||
uint32_t checksum = 0;
|
||||
|
||||
auto write_interleaved_bytes = [&](const Bytes& bytes)
|
||||
{
|
||||
Bytes interleaved = amigaInterleave(bytes);
|
||||
Bytes mfm = encodeMfm(interleaved, lastBit);
|
||||
checksum ^= amigaChecksum(mfm);
|
||||
checksum &= 0x55555555;
|
||||
write_bits(bits, cursor, mfm);
|
||||
};
|
||||
|
||||
auto write_interleaved_word = [&](uint32_t word)
|
||||
{
|
||||
Bytes b(4);
|
||||
b.writer().write_be32(word);
|
||||
write_interleaved_bytes(b);
|
||||
};
|
||||
|
||||
write_bits(bits, cursor, AMIGA_SECTOR_RECORD, 6*8);
|
||||
|
||||
checksum = 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(header);
|
||||
Bytes recoveryInfo(16);
|
||||
if (sector->data.size() == 528)
|
||||
recoveryInfo = sector->data.slice(512, 16);
|
||||
write_interleaved_bytes(recoveryInfo);
|
||||
write_interleaved_word(checksum);
|
||||
|
||||
Bytes data = sector->data.slice(0, 512);
|
||||
write_interleaved_word(amigaChecksum(encodeMfm(amigaInterleave(data), lastBit)));
|
||||
write_interleaved_bytes(data);
|
||||
}
|
||||
|
||||
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 / _config.clock_rate_us();
|
||||
std::vector<bool> bits(bitsPerRevolution);
|
||||
unsigned cursor = 0;
|
||||
|
||||
fillBitmapTo(bits, cursor, _config.post_index_gap_ms() * 1000 / _config.clock_rate_us(), { 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, _config.clock_rate_us()*1e3);
|
||||
return fluxmap;
|
||||
}
|
||||
|
||||
@@ -9,10 +9,12 @@
|
||||
|
||||
class Sector;
|
||||
class Fluxmap;
|
||||
class Apple2DecoderProto;
|
||||
|
||||
class Apple2Decoder : public AbstractDecoder
|
||||
{
|
||||
public:
|
||||
Apple2Decoder(const Apple2DecoderProto&) {}
|
||||
virtual ~Apple2Decoder() {}
|
||||
|
||||
RecordType advanceToNextRecord();
|
||||
|
||||
4
arch/apple2/apple2.proto
Normal file
4
arch/apple2/apple2.proto
Normal file
@@ -0,0 +1,4 @@
|
||||
syntax = "proto2";
|
||||
|
||||
message Apple2DecoderProto {}
|
||||
|
||||
@@ -9,15 +9,20 @@
|
||||
#define BROTHER_DATA_RECORD_CHECKSUM 3
|
||||
#define BROTHER_DATA_RECORD_ENCODED_SIZE 415
|
||||
|
||||
#define BROTHER_TRACKS_PER_DISK 78
|
||||
#define BROTHER_TRACKS_PER_240KB_DISK 78
|
||||
#define BROTHER_TRACKS_PER_120KB_DISK 39
|
||||
#define BROTHER_SECTORS_PER_TRACK 12
|
||||
|
||||
class Sector;
|
||||
class SectorSet;
|
||||
class Fluxmap;
|
||||
class BrotherDecoderProto;
|
||||
class BrotherEncoderProto;
|
||||
|
||||
class BrotherDecoder : public AbstractDecoder
|
||||
{
|
||||
public:
|
||||
BrotherDecoder(const BrotherDecoderProto& config) {}
|
||||
virtual ~BrotherDecoder() {}
|
||||
|
||||
RecordType advanceToNextRecord();
|
||||
@@ -28,12 +33,17 @@ public:
|
||||
class BrotherEncoder : public AbstractEncoder
|
||||
{
|
||||
public:
|
||||
BrotherEncoder(const BrotherEncoderProto& config):
|
||||
_config(config)
|
||||
{}
|
||||
|
||||
virtual ~BrotherEncoder() {}
|
||||
|
||||
private:
|
||||
const BrotherEncoderProto& _config;
|
||||
|
||||
public:
|
||||
std::unique_ptr<Fluxmap> encode(int physicalTrack, int physicalSide, const SectorSet& allSectors);
|
||||
};
|
||||
|
||||
extern FlagGroup brotherEncoderFlags;
|
||||
|
||||
#endif
|
||||
|
||||
20
arch/brother/brother.proto
Normal file
20
arch/brother/brother.proto
Normal file
@@ -0,0 +1,20 @@
|
||||
syntax = "proto2";
|
||||
|
||||
message BrotherDecoderProto {}
|
||||
|
||||
enum BrotherFormat {
|
||||
BROTHER240 = 0;
|
||||
BROTHER120 = 1;
|
||||
};
|
||||
|
||||
message BrotherEncoderProto {
|
||||
optional double clock_rate_us = 1 [default = 3.83];
|
||||
optional double post_index_gap_ms = 2 [default = 1.0];
|
||||
optional double sector_spacing_ms = 3 [default = 16.2];
|
||||
optional double post_header_spacing_ms = 4 [default = 0.69];
|
||||
optional string sector_skew = 5 [default = "05a3816b4927"];
|
||||
|
||||
optional BrotherFormat format = 6 [default = BROTHER240];
|
||||
optional int32 bias = 7 [default = 0];
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "crc.h"
|
||||
#include "sectorset.h"
|
||||
#include "writer.h"
|
||||
#include "arch/brother/brother.pb.h"
|
||||
|
||||
FlagGroup brotherEncoderFlags;
|
||||
|
||||
@@ -129,9 +130,25 @@ static int charToInt(char c)
|
||||
std::unique_ptr<Fluxmap> BrotherEncoder::encode(
|
||||
int physicalTrack, int physicalSide, const SectorSet& allSectors)
|
||||
{
|
||||
if ((physicalTrack < 0) || (physicalTrack >= BROTHER_TRACKS_PER_DISK)
|
||||
|| (physicalSide != 0))
|
||||
int logicalTrack;
|
||||
if (physicalSide != 0)
|
||||
return std::unique_ptr<Fluxmap>();
|
||||
physicalTrack -= _config.bias();
|
||||
switch (_config.format())
|
||||
{
|
||||
case BROTHER120:
|
||||
if ((physicalTrack < 0) || (physicalTrack >= (BROTHER_TRACKS_PER_120KB_DISK*2))
|
||||
|| (physicalTrack & 1))
|
||||
return std::unique_ptr<Fluxmap>();
|
||||
logicalTrack = physicalTrack/2;
|
||||
break;
|
||||
|
||||
case BROTHER240:
|
||||
if ((physicalTrack < 0) || (physicalTrack >= BROTHER_TRACKS_PER_240KB_DISK))
|
||||
return std::unique_ptr<Fluxmap>();
|
||||
logicalTrack = physicalTrack;
|
||||
break;
|
||||
}
|
||||
|
||||
int bitsPerRevolution = 200000.0 / clockRateUs;
|
||||
const std::string& skew = sectorSkew.get();
|
||||
@@ -146,15 +163,15 @@ std::unique_ptr<Fluxmap> BrotherEncoder::encode(
|
||||
double dataMs = headerMs + postHeaderSpacingMs;
|
||||
unsigned dataCursor = dataMs*1e3 / clockRateUs;
|
||||
|
||||
const auto& sectorData = allSectors.get(physicalTrack, 0, sectorId);
|
||||
const auto& sectorData = allSectors.get(logicalTrack, 0, sectorId);
|
||||
|
||||
fillBitmapTo(bits, cursor, headerCursor, { true, false });
|
||||
write_sector_header(bits, cursor, physicalTrack, sectorId);
|
||||
write_sector_header(bits, cursor, logicalTrack, sectorId);
|
||||
fillBitmapTo(bits, cursor, dataCursor, { true, false });
|
||||
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 });
|
||||
|
||||
|
||||
@@ -1,16 +1,42 @@
|
||||
#ifndef C64_H
|
||||
#define C64_H
|
||||
|
||||
#include "decoders/decoders.h"
|
||||
#include "encoders/encoders.h"
|
||||
|
||||
#define C64_SECTOR_RECORD 0xffd49
|
||||
#define C64_DATA_RECORD 0xffd57
|
||||
#define C64_SECTOR_LENGTH 256
|
||||
|
||||
/* Source: http://www.unusedino.de/ec64/technical/formats/g64.html
|
||||
1. Header sync FF FF FF FF FF (40 'on' bits, not GCR)
|
||||
2. Header info 52 54 B5 29 4B 7A 5E 95 55 55 (10 GCR bytes)
|
||||
3. Header gap 55 55 55 55 55 55 55 55 55 (9 bytes, never read)
|
||||
4. Data sync FF FF FF FF FF (40 'on' bits, not GCR)
|
||||
5. Data block 55...4A (325 GCR bytes)
|
||||
6. Inter-sector gap 55 55 55 55...55 55 (4 to 12 bytes, never read)
|
||||
1. Header sync (SYNC for the next sector)
|
||||
*/
|
||||
#define C64_HEADER_DATA_SYNC 0xFF
|
||||
#define C64_HEADER_BLOCK_ID 0x08
|
||||
#define C64_DATA_BLOCK_ID 0x07
|
||||
#define C64_HEADER_GAP 0x55
|
||||
#define C64_INTER_SECTOR_GAP 0x55
|
||||
#define C64_PADDING 0x0F
|
||||
|
||||
#define C64_TRACKS_PER_DISK 40
|
||||
#define C64_BAM_TRACK 17
|
||||
|
||||
|
||||
class Sector;
|
||||
class Fluxmap;
|
||||
class Commodore64DecoderProto;
|
||||
class Commodore64EncoderProto;
|
||||
|
||||
class Commodore64Decoder : public AbstractDecoder
|
||||
{
|
||||
public:
|
||||
Commodore64Decoder(const Commodore64DecoderProto&) {}
|
||||
virtual ~Commodore64Decoder() {}
|
||||
|
||||
RecordType advanceToNextRecord();
|
||||
@@ -18,4 +44,25 @@ public:
|
||||
void decodeDataRecord();
|
||||
};
|
||||
|
||||
class Commodore64Encoder : public AbstractEncoder
|
||||
{
|
||||
public:
|
||||
Commodore64Encoder(const Commodore64EncoderProto& config):
|
||||
_config(config)
|
||||
{}
|
||||
|
||||
virtual ~Commodore64Encoder() {}
|
||||
|
||||
public:
|
||||
std::unique_ptr<Fluxmap> encode(int physicalTrack, int physicalSide, const SectorSet& allSectors);
|
||||
|
||||
private:
|
||||
void writeSector(std::vector<bool>& bits, unsigned& cursor, const Sector* sector) const;
|
||||
|
||||
private:
|
||||
const Commodore64EncoderProto& _config;
|
||||
uint8_t _formatByte1;
|
||||
uint8_t _formatByte2;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
13
arch/c64/c64.proto
Normal file
13
arch/c64/c64.proto
Normal file
@@ -0,0 +1,13 @@
|
||||
syntax = "proto2";
|
||||
|
||||
import "lib/common.proto";
|
||||
|
||||
message Commodore64DecoderProto {}
|
||||
|
||||
message Commodore64EncoderProto {
|
||||
optional double post_index_gap_us = 1 [default=0.0,
|
||||
(help) = "post-index gap before first sector header."];
|
||||
optional double clock_compensation_factor = 2 [default=1.0,
|
||||
(help) = "scale the output clock by this much."];
|
||||
}
|
||||
|
||||
349
arch/c64/encoder.cc
Normal file
349
arch/c64/encoder.cc
Normal file
@@ -0,0 +1,349 @@
|
||||
#include "globals.h"
|
||||
#include "record.h"
|
||||
#include "decoders/decoders.h"
|
||||
#include "encoders/encoders.h"
|
||||
#include "c64.h"
|
||||
#include "crc.h"
|
||||
#include "sectorset.h"
|
||||
#include "sector.h"
|
||||
#include "writer.h"
|
||||
#include "fmt/format.h"
|
||||
#include "arch/c64/c64.pb.h"
|
||||
#include <ctype.h>
|
||||
#include "bytes.h"
|
||||
|
||||
static bool lastBit;
|
||||
|
||||
static double clockRateUsForTrack(unsigned track)
|
||||
{
|
||||
/*
|
||||
* Track # Sectors/Track Speed Zone bits/rotation
|
||||
* 1 – 17 21 3 61,538.4
|
||||
* 18 – 24 19 2 57,142.8
|
||||
* 25 – 30 18 1 53,333.4
|
||||
* 31 – 35 17 0 50,000.0
|
||||
*/
|
||||
if (track < 17)
|
||||
return 200000.0/61538.4;
|
||||
if (track < 24)
|
||||
return 200000.0/57142.8;
|
||||
if (track < 30)
|
||||
return 200000.0/53333.4;
|
||||
return 200000.0/50000.0;
|
||||
|
||||
}
|
||||
|
||||
static unsigned sectorsForTrack(unsigned track)
|
||||
{
|
||||
/*
|
||||
* Track Sectors/track # Sectors Storage in Bytes
|
||||
* ----- ------------- --------- ----------------
|
||||
* 1-17 21 357 7820
|
||||
* 18-24 19 133 7170
|
||||
* 25-30 18 108 6300
|
||||
* 31-40(*) 17 85 6020
|
||||
* ---
|
||||
* 683 (for a 35 track image)
|
||||
*/
|
||||
if (track < 17)
|
||||
return 21;
|
||||
if (track < 24)
|
||||
return 19;
|
||||
if (track < 30)
|
||||
return 18;
|
||||
return 17;
|
||||
}
|
||||
|
||||
static int encode_data_gcr(uint8_t data)
|
||||
{
|
||||
switch (data)
|
||||
{
|
||||
#define GCR_ENTRY(gcr, data) \
|
||||
case data: return gcr;
|
||||
#include "data_gcr.h"
|
||||
#undef GCR_ENTRY
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
|
||||
static void write_bits(std::vector<bool>& bits, unsigned& cursor, const std::vector<bool>& src)
|
||||
{
|
||||
for (bool bit : src) //Range-based for loop
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
void bindump(std::ostream& stream, std::vector<bool>& buffer)
|
||||
{
|
||||
size_t pos = 0;
|
||||
|
||||
while ((pos < buffer.size()) and (pos <520))
|
||||
{
|
||||
stream << fmt::format("{:5d} : ", pos);
|
||||
for (int i=0; i<40; i++)
|
||||
{
|
||||
if ((pos+i) < buffer.size())
|
||||
stream << fmt::format("{:01b}", (buffer[pos+i]));
|
||||
else
|
||||
stream << "-- ";
|
||||
if ((((pos + i + 1) % 8) == 0) and i != 0)
|
||||
stream << " ";
|
||||
|
||||
}
|
||||
stream << std::endl;
|
||||
pos += 40;
|
||||
}
|
||||
}
|
||||
static std::vector<bool> encode_data(uint8_t input)
|
||||
{
|
||||
/*
|
||||
* Four 8-bit data bytes are converted to four 10-bit GCR bytes at a time by
|
||||
* the 1541 DOS. RAM is only an 8-bit storage device though. This hardware
|
||||
* limitation prevents a 10-bit GCR byte from being stored in a single
|
||||
* memory location. Four 10-bit GCR bytes total 40 bits - a number evenly
|
||||
* divisible by our overriding 8-bit constraint. Commodore sub- divides the
|
||||
* 40 GCR bits into five 8-bit bytes to solve this dilemma. This explains
|
||||
* why four 8-bit data bytes are converted to GCR form at a time. The
|
||||
* following step by step example demonstrates how this bit manipulation is
|
||||
* performed by the DOS.
|
||||
*
|
||||
* STEP 1. Four 8-bit Data Bytes
|
||||
* $08 $10 $00 $12
|
||||
*
|
||||
* STEP 2. Hexadecimal to Binary Conversion
|
||||
* 1. Binary Equivalents
|
||||
* $08 $10 $00 $12
|
||||
* 00001000 00010000 00000000 00010010
|
||||
*
|
||||
* STEP 3. Binary to GCR Conversion
|
||||
* 1. Four 8-bit Data Bytes
|
||||
* 00001000 00010000 00000000 00010010
|
||||
* 2. High and Low Nybbles
|
||||
* 0000 1000 0001 0000 0000 0000 0001 0010
|
||||
* 3. High and Low Nybble GCR Equivalents
|
||||
* 01010 01001 01011 01010 01010 01010 01011 10010
|
||||
* 4. Four 10-bit GCR Bytes
|
||||
* 0101001001 0101101010 0101001010 0101110010
|
||||
*
|
||||
* STEP 4. 10-bit GCR to 8-bit GCR Conversion
|
||||
* 1. Concatenate Four 10-bit GCR Bytes
|
||||
* 0101001001010110101001010010100101110010
|
||||
* 2. Five 8-bit Subdivisions
|
||||
* 01010010 01010110 10100101 00101001 01110010
|
||||
*
|
||||
* STEP 5. Binary to Hexadecimal Conversion
|
||||
* 1. Hexadecimal Equivalents
|
||||
* 01010010 01010110 10100101 00101001 01110010
|
||||
* $52 $56 $A5 $29 $72
|
||||
*
|
||||
* STEP 6. Four 8-bit Data Bytes are Recorded as Five 8-bit GCR Bytes
|
||||
* $08 $10 $00 $12
|
||||
*
|
||||
* are recorded as
|
||||
* $52 $56 $A5 $29 $72
|
||||
*/
|
||||
|
||||
std::vector<bool> output(10, false);
|
||||
uint8_t hi = 0;
|
||||
uint8_t lo = 0;
|
||||
uint8_t lo_GCR = 0;
|
||||
uint8_t hi_GCR = 0;
|
||||
|
||||
//Convert the byte in high and low nibble
|
||||
lo = input >> 4; //get the lo nibble shift the bits 4 to the right
|
||||
hi = input & 15; //get the hi nibble bij masking the lo bits (00001111)
|
||||
|
||||
|
||||
lo_GCR = encode_data_gcr(lo); //example value: 0000 GCR = 01010
|
||||
hi_GCR = encode_data_gcr(hi); //example value: 1000 GCR = 01001
|
||||
//output = [0,1,2,3,4,5,6,7,8,9]
|
||||
//value = [0,1,0,1,0,0,1,0,0,1]
|
||||
// 01010 01001
|
||||
|
||||
int b = 4;
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
if (i < 5) //01234
|
||||
{ //i = 0 op
|
||||
output[4-i] = (lo_GCR & 1); //01010
|
||||
|
||||
//01010 -> & 00001 -> 00000 output[4] = 0
|
||||
//00101 -> & 00001 -> 00001 output[3] = 1
|
||||
//00010 -> & 00001 -> 00000 output[2] = 0
|
||||
//00001 -> & 00001 -> 00001 output[1] = 1
|
||||
//00000 -> & 00001 -> 00000 output[0] = 0
|
||||
lo_GCR >>= 1;
|
||||
} else
|
||||
{
|
||||
output[i+b] = (hi_GCR & 1); //01001
|
||||
//01001 -> & 00001 -> 00001 output[9] = 1
|
||||
//00100 -> & 00001 -> 00000 output[8] = 0
|
||||
//00010 -> & 00001 -> 00000 output[7] = 0
|
||||
//00001 -> & 00001 -> 00001 output[6] = 1
|
||||
//00000 -> & 00001 -> 00000 output[5] = 0
|
||||
hi_GCR >>= 1;
|
||||
b = b-2;
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
void Commodore64Encoder::writeSector(std::vector<bool>& bits, unsigned& cursor, const Sector* sector) const
|
||||
{
|
||||
/* Source: http://www.unusedino.de/ec64/technical/formats/g64.html
|
||||
* 1. Header sync FF FF FF FF FF (40 'on' bits, not GCR)
|
||||
* 2. Header info 52 54 B5 29 4B 7A 5E 95 55 55 (10 GCR bytes)
|
||||
* 3. Header gap 55 55 55 55 55 55 55 55 55 (9 bytes, never read)
|
||||
* 4. Data sync FF FF FF FF FF (40 'on' bits, not GCR)
|
||||
* 5. Data block 55...4A (325 GCR bytes)
|
||||
* 6. Inter-sector gap 55 55 55 55...55 55 (4 to 12 bytes, never read)
|
||||
* 1. Header sync (SYNC for the next sector)
|
||||
*/
|
||||
if ((sector->status == Sector::OK) or (sector->status == Sector::BAD_CHECKSUM))
|
||||
{
|
||||
// There is data to encode to disk.
|
||||
if ((sector->data.size() != C64_SECTOR_LENGTH))
|
||||
Error() << fmt::format("unsupported sector size {} --- you must pick 256", sector->data.size());
|
||||
|
||||
// 1. Write header Sync (not GCR)
|
||||
for (int i=0; i<6; i++)
|
||||
write_bits(bits, cursor, C64_HEADER_DATA_SYNC, 1*8); /* sync */
|
||||
|
||||
// 2. Write Header info 10 GCR bytes
|
||||
/*
|
||||
* The 10 byte header info (#2) is GCR encoded and must be decoded to
|
||||
* it's normal 8 bytes to be understood. Once decoded, its breakdown is
|
||||
* as follows:
|
||||
*
|
||||
* Byte $00 - header block ID ($08)
|
||||
* 01 - header block checksum 16 (EOR of $02-$05)
|
||||
* 02 - Sector
|
||||
* 03 - Track
|
||||
* 04 - Format ID byte #2
|
||||
* 05 - Format ID byte #1
|
||||
* 06-07 - $0F ("off" bytes)
|
||||
*/
|
||||
uint8_t encodedTrack = ((sector->logicalTrack) + 1); // C64 track numbering starts with 1. Fluxengine with 0.
|
||||
uint8_t encodedSector = sector->logicalSector;
|
||||
// uint8_t formatByte1 = C64_FORMAT_ID_BYTE1;
|
||||
// uint8_t formatByte2 = C64_FORMAT_ID_BYTE2;
|
||||
uint8_t headerChecksum = (encodedTrack ^ encodedSector ^ _formatByte1 ^ _formatByte2);
|
||||
write_bits(bits, cursor, encode_data(C64_HEADER_BLOCK_ID));
|
||||
write_bits(bits, cursor, encode_data(headerChecksum));
|
||||
write_bits(bits, cursor, encode_data(encodedSector));
|
||||
write_bits(bits, cursor, encode_data(encodedTrack));
|
||||
write_bits(bits, cursor, encode_data(_formatByte2));
|
||||
write_bits(bits, cursor, encode_data(_formatByte1));
|
||||
write_bits(bits, cursor, encode_data(C64_PADDING));
|
||||
write_bits(bits, cursor, encode_data(C64_PADDING));
|
||||
|
||||
// 3. Write header GAP not GCR
|
||||
for (int i=0; i<9; i++)
|
||||
write_bits(bits, cursor, C64_HEADER_GAP, 1*8); /* header gap */
|
||||
|
||||
// 4. Write Data sync not GCR
|
||||
for (int i=0; i<6; i++)
|
||||
write_bits(bits, cursor, C64_HEADER_DATA_SYNC, 1*8); /* sync */
|
||||
|
||||
// 5. Write data block 325 GCR bytes
|
||||
/*
|
||||
* The 325 byte data block (#5) is GCR encoded and must be decoded to its
|
||||
* normal 260 bytes to be understood. The data block is made up of the following:
|
||||
*
|
||||
* Byte $00 - data block ID ($07)
|
||||
* 01-100 - 256 bytes data
|
||||
* 101 - data block checksum (EOR of $01-100)
|
||||
* 102-103 - $00 ("off" bytes, to make the sector size a multiple of 5)
|
||||
*/
|
||||
|
||||
write_bits(bits, cursor, encode_data(C64_DATA_BLOCK_ID));
|
||||
uint8_t dataChecksum = xorBytes(sector->data);
|
||||
ByteReader br(sector->data);
|
||||
int i = 0;
|
||||
for (i = 0; i < C64_SECTOR_LENGTH; i++)
|
||||
{
|
||||
uint8_t val = br.read_8();
|
||||
write_bits(bits, cursor, encode_data(val));
|
||||
}
|
||||
write_bits(bits, cursor, encode_data(dataChecksum));
|
||||
write_bits(bits, cursor, encode_data(C64_PADDING));
|
||||
write_bits(bits, cursor, encode_data(C64_PADDING));
|
||||
|
||||
//6. Write inter-sector gap 9 - 12 bytes nor gcr
|
||||
for (int i=0; i<9; i++)
|
||||
write_bits(bits, cursor, C64_INTER_SECTOR_GAP, 1*8); /* sync */
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<Fluxmap> Commodore64Encoder::encode(
|
||||
int physicalTrack, int physicalSide, const SectorSet& allSectors)
|
||||
{
|
||||
/* The format ID Character # 1 and # 2 are in the .d64 image only present
|
||||
* in track 18 sector zero which contains the BAM info in byte 162 and 163.
|
||||
* it is written in every header of every sector and track. headers are not
|
||||
* stored in a d64 disk image so we have to get it from track 18 which
|
||||
* contains the BAM.
|
||||
*/
|
||||
|
||||
const auto& sectorData = allSectors.get(C64_BAM_TRACK*2, 0, 0); //Read de BAM to get the DISK ID bytes
|
||||
if (sectorData)
|
||||
{
|
||||
ByteReader br(sectorData->data);
|
||||
br.seek(162); //goto position of the first Disk ID Byte
|
||||
_formatByte1 = br.read_8();
|
||||
_formatByte2 = br.read_8();
|
||||
}
|
||||
else
|
||||
_formatByte1 = _formatByte2 = 0;
|
||||
|
||||
int logicalTrack = physicalTrack / 2;
|
||||
double clockRateUs = clockRateUsForTrack(logicalTrack) * _config.clock_compensation_factor();
|
||||
|
||||
int bitsPerRevolution = 200000.0 / clockRateUs;
|
||||
|
||||
std::vector<bool> bits(bitsPerRevolution);
|
||||
unsigned cursor = 0;
|
||||
|
||||
fillBitmapTo(bits, cursor, _config.post_index_gap_us() / clockRateUs, { true, false });
|
||||
lastBit = false;
|
||||
|
||||
unsigned numSectors = sectorsForTrack(logicalTrack);
|
||||
unsigned writtenSectors = 0;
|
||||
for (int sectorId=0; sectorId<numSectors; sectorId++)
|
||||
{
|
||||
const auto& sectorData = allSectors.get(physicalTrack, physicalSide, sectorId);
|
||||
if (sectorData)
|
||||
{
|
||||
writeSector(bits, cursor, sectorData);
|
||||
writtenSectors++;
|
||||
}
|
||||
}
|
||||
if (writtenSectors == 0)
|
||||
return std::unique_ptr<Fluxmap>();
|
||||
|
||||
if (cursor >= bits.size())
|
||||
Error() << fmt::format("track data overrun by {} bits", cursor - bits.size());
|
||||
fillBitmapTo(bits, cursor, bits.size(), { true, false });
|
||||
|
||||
std::unique_ptr<Fluxmap> fluxmap(new Fluxmap);
|
||||
fluxmap->appendBits(bits, clockRateUs*1e3);
|
||||
return fluxmap;
|
||||
}
|
||||
|
||||
// vim: sw=4 ts=4 et
|
||||
|
||||
@@ -7,10 +7,12 @@
|
||||
|
||||
class Sector;
|
||||
class Fluxmap;
|
||||
class F85DecoderProto;
|
||||
|
||||
class DurangoF85Decoder : public AbstractDecoder
|
||||
{
|
||||
public:
|
||||
DurangoF85Decoder(const F85DecoderProto&) {}
|
||||
virtual ~DurangoF85Decoder() {}
|
||||
|
||||
RecordType advanceToNextRecord();
|
||||
|
||||
4
arch/f85/f85.proto
Normal file
4
arch/f85/f85.proto
Normal file
@@ -0,0 +1,4 @@
|
||||
syntax = "proto2";
|
||||
|
||||
message F85DecoderProto {}
|
||||
|
||||
@@ -8,10 +8,12 @@
|
||||
class Sector;
|
||||
class Fluxmap;
|
||||
class Track;
|
||||
class Fb100DecoderProto;
|
||||
|
||||
class Fb100Decoder : public AbstractDecoder
|
||||
{
|
||||
public:
|
||||
Fb100Decoder(const Fb100DecoderProto&) {}
|
||||
virtual ~Fb100Decoder() {}
|
||||
|
||||
RecordType advanceToNextRecord();
|
||||
|
||||
4
arch/fb100/fb100.proto
Normal file
4
arch/fb100/fb100.proto
Normal file
@@ -0,0 +1,4 @@
|
||||
syntax = "proto2";
|
||||
|
||||
message Fb100DecoderProto {}
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#include "decoders/fluxmapreader.h"
|
||||
#include "sector.h"
|
||||
#include "record.h"
|
||||
#include "arch/ibm/ibm.pb.h"
|
||||
#include "proto.h"
|
||||
#include <string.h>
|
||||
|
||||
static_assert(std::is_trivially_copyable<IbmIdam>::value,
|
||||
@@ -57,11 +59,11 @@ const FluxPattern FM_TRS80DAM1_PATTERN(16, 0xf56b);
|
||||
|
||||
/*
|
||||
* TRS80DAM2 record:
|
||||
* flux: XXXX-X-X-XX-XXX- = 0xf56c
|
||||
* flux: XXXX-X-X-XX-XXX- = 0xf56e
|
||||
* clock: X X - - - X X X = 0xc7
|
||||
* data: X X X X X - X - = 0xfa
|
||||
*/
|
||||
const FluxPattern FM_TRS80DAM2_PATTERN(16, 0xf56c);
|
||||
const FluxPattern FM_TRS80DAM2_PATTERN(16, 0xf56e);
|
||||
|
||||
/* MFM record separator:
|
||||
* 0xA1 is:
|
||||
@@ -73,8 +75,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(
|
||||
{
|
||||
@@ -87,6 +91,11 @@ const FluxMatchers ANY_RECORD_PATTERN(
|
||||
}
|
||||
);
|
||||
|
||||
std::set<unsigned> IbmDecoder::requiredSectors(Track& track) const
|
||||
{
|
||||
return iterate(_config.required_sectors());
|
||||
}
|
||||
|
||||
AbstractDecoder::RecordType IbmDecoder::advanceToNextRecord()
|
||||
{
|
||||
const FluxMatcher* matcher = nullptr;
|
||||
@@ -100,7 +109,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)
|
||||
@@ -128,12 +138,15 @@ void IbmDecoder::decodeSectorRecord()
|
||||
br.read_8(); /* skip ID byte */
|
||||
_sector->logicalTrack = br.read_8();
|
||||
_sector->logicalSide = br.read_8();
|
||||
_sector->logicalSector = br.read_8() - _sectorBase;
|
||||
_sector->logicalSector = br.read_8() - _config.sector_id_base();
|
||||
_currentSectorSize = 1 << (br.read_8() + 7);
|
||||
uint16_t wantCrc = br.read_be16();
|
||||
uint16_t gotCrc = crc16(CCITT_POLY, bytes.slice(0, _currentHeaderLength + 5));
|
||||
if (wantCrc == gotCrc)
|
||||
_sector->status = Sector::DATA_MISSING; /* correct but unintuitive */
|
||||
|
||||
if (_config.ignore_side_byte())
|
||||
_sector->logicalSide = _sector->physicalSide;
|
||||
}
|
||||
|
||||
void IbmDecoder::decodeDataRecord()
|
||||
|
||||
258
arch/ibm/encoder.cc
Normal file
258
arch/ibm/encoder.cc
Normal file
@@ -0,0 +1,258 @@
|
||||
#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 "arch/ibm/ibm.pb.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;
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t decodeUint16(uint16_t raw)
|
||||
{
|
||||
Bytes b;
|
||||
ByteWriter bw(b);
|
||||
bw.write_be16(raw);
|
||||
return decodeFmMfm(b.toBits())[0];
|
||||
}
|
||||
|
||||
void IbmEncoder::getTrackFormat(IbmEncoderProto::TrackdataProto& trackdata, unsigned cylinder, unsigned head)
|
||||
{
|
||||
trackdata.Clear();
|
||||
for (const auto& f : _config.trackdata())
|
||||
{
|
||||
if (f.has_cylinder() && (f.cylinder() != cylinder))
|
||||
continue;
|
||||
if (f.has_head() && (f.head() != head))
|
||||
continue;
|
||||
|
||||
trackdata.MergeFrom(f);
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<Fluxmap> IbmEncoder::encode(
|
||||
int physicalTrack, int physicalSide, const SectorSet& allSectors)
|
||||
{
|
||||
IbmEncoderProto::TrackdataProto trackdata;
|
||||
getTrackFormat(trackdata, physicalTrack, physicalSide);
|
||||
|
||||
auto writeBytes = [&](const Bytes& bytes)
|
||||
{
|
||||
if (trackdata.use_fm())
|
||||
encodeFm(_bits, _cursor, bytes);
|
||||
else
|
||||
encodeMfm(_bits, _cursor, bytes, _lastBit);
|
||||
};
|
||||
|
||||
auto writeFillerBytes = [&](int count, uint8_t byte)
|
||||
{
|
||||
Bytes bytes = { byte };
|
||||
for (int i=0; i<count; i++)
|
||||
writeBytes(bytes);
|
||||
};
|
||||
|
||||
if (trackdata.swap_sides())
|
||||
physicalSide = 1 - physicalSide;
|
||||
double clockRateUs = 1e3 / trackdata.clock_rate_khz();
|
||||
if (!trackdata.use_fm())
|
||||
clockRateUs /= 2.0;
|
||||
int bitsPerRevolution = (trackdata.track_length_ms() * 1000.0) / clockRateUs;
|
||||
_bits.resize(bitsPerRevolution);
|
||||
_cursor = 0;
|
||||
|
||||
uint8_t idamUnencoded = decodeUint16(trackdata.idam_byte());
|
||||
uint8_t damUnencoded = decodeUint16(trackdata.dam_byte());
|
||||
|
||||
uint8_t sectorSize = 0;
|
||||
{
|
||||
int s = trackdata.sector_size() >> 7;
|
||||
while (s > 1)
|
||||
{
|
||||
s >>= 1;
|
||||
sectorSize += 1;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t gapFill = trackdata.use_fm() ? 0x00 : 0x4e;
|
||||
|
||||
writeFillerBytes(trackdata.gap0(), gapFill);
|
||||
if (trackdata.emit_iam())
|
||||
{
|
||||
writeFillerBytes(trackdata.use_fm() ? 6 : 12, 0x00);
|
||||
if (!trackdata.use_fm())
|
||||
{
|
||||
for (int i=0; i<3; i++)
|
||||
writeRawBits(MFM_IAM_SEPARATOR, 16);
|
||||
}
|
||||
writeRawBits(trackdata.use_fm() ? FM_IAM_RECORD : MFM_IAM_RECORD, 16);
|
||||
writeFillerBytes(trackdata.gap1(), gapFill);
|
||||
}
|
||||
|
||||
bool first = true;
|
||||
for (char sectorChar : trackdata.sector_skew())
|
||||
{
|
||||
int sectorId = charToInt(sectorChar);
|
||||
if (!first)
|
||||
writeFillerBytes(trackdata.gap3(), gapFill);
|
||||
first = false;
|
||||
|
||||
const auto& sectorData = allSectors.get(physicalTrack, physicalSide, sectorId);
|
||||
if (!sectorData)
|
||||
{
|
||||
/* If there are any missing sectors, this is an empty track. */
|
||||
return std::unique_ptr<Fluxmap>();
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
writeFillerBytes(trackdata.use_fm() ? 6 : 12, 0x00);
|
||||
if (!trackdata.use_fm())
|
||||
{
|
||||
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 + trackdata.start_sector_id());
|
||||
bw.write_8(sectorSize);
|
||||
uint16_t crc = crc16(CCITT_POLY, header);
|
||||
bw.write_be16(crc);
|
||||
|
||||
int conventionalHeaderStart = 0;
|
||||
if (!trackdata.use_fm())
|
||||
{
|
||||
for (int i=0; i<3; i++)
|
||||
writeRawBits(MFM_RECORD_SEPARATOR, 16);
|
||||
conventionalHeaderStart += 3;
|
||||
|
||||
}
|
||||
writeRawBits(trackdata.idam_byte(), 16);
|
||||
conventionalHeaderStart += 1;
|
||||
|
||||
writeBytes(header.slice(conventionalHeaderStart));
|
||||
}
|
||||
|
||||
writeFillerBytes(trackdata.gap2(), gapFill);
|
||||
|
||||
{
|
||||
Bytes data;
|
||||
ByteWriter bw(data);
|
||||
|
||||
writeFillerBytes(trackdata.use_fm() ? 6 : 12, 0x00);
|
||||
if (!trackdata.use_fm())
|
||||
{
|
||||
for (int i=0; i<3; i++)
|
||||
bw.write_8(MFM_RECORD_SEPARATOR_BYTE);
|
||||
}
|
||||
bw.write_8(damUnencoded);
|
||||
|
||||
Bytes truncatedData = sectorData->data.slice(0, trackdata.sector_size());
|
||||
bw += truncatedData;
|
||||
uint16_t crc = crc16(CCITT_POLY, data);
|
||||
bw.write_be16(crc);
|
||||
|
||||
int conventionalHeaderStart = 0;
|
||||
if (!trackdata.use_fm())
|
||||
{
|
||||
for (int i=0; i<3; i++)
|
||||
writeRawBits(MFM_RECORD_SEPARATOR, 16);
|
||||
conventionalHeaderStart += 3;
|
||||
|
||||
}
|
||||
writeRawBits(trackdata.dam_byte(), 16);
|
||||
conventionalHeaderStart += 1;
|
||||
|
||||
writeBytes(data.slice(conventionalHeaderStart));
|
||||
}
|
||||
}
|
||||
|
||||
if (_cursor >= _bits.size())
|
||||
Error() << "track data overrun";
|
||||
while (_cursor < _bits.size())
|
||||
writeFillerBytes(1, gapFill);
|
||||
|
||||
std::unique_ptr<Fluxmap> fluxmap(new Fluxmap);
|
||||
fluxmap->appendBits(_bits, clockRateUs*1e3);
|
||||
return fluxmap;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
#define IBM_H
|
||||
|
||||
#include "decoders/decoders.h"
|
||||
#include "encoders/encoders.h"
|
||||
#include "arch/ibm/ibm.pb.h"
|
||||
|
||||
/* IBM format (i.e. ordinary PC floppies). */
|
||||
|
||||
@@ -31,66 +33,45 @@ struct IbmIdam
|
||||
class IbmDecoder : public AbstractDecoder
|
||||
{
|
||||
public:
|
||||
IbmDecoder(unsigned sectorBase):
|
||||
_sectorBase(sectorBase)
|
||||
IbmDecoder(const IbmDecoderProto& config):
|
||||
_config(config)
|
||||
{}
|
||||
|
||||
RecordType advanceToNextRecord();
|
||||
void decodeSectorRecord();
|
||||
void decodeDataRecord();
|
||||
|
||||
std::set<unsigned> requiredSectors(Track& track) const;
|
||||
|
||||
private:
|
||||
unsigned _sectorBase;
|
||||
const IbmDecoderProto& _config;
|
||||
unsigned _currentSectorSize;
|
||||
unsigned _currentHeaderLength;
|
||||
};
|
||||
|
||||
#if 0
|
||||
class AbstractIbmDecoder : public AbstractSoftSectorDecoder
|
||||
class IbmEncoder : public AbstractEncoder
|
||||
{
|
||||
public:
|
||||
AbstractIbmDecoder(unsigned sectorIdBase):
|
||||
_sectorIdBase(sectorIdBase)
|
||||
{}
|
||||
virtual ~AbstractIbmDecoder() {}
|
||||
IbmEncoder(const IbmEncoderProto& config):
|
||||
_config(config)
|
||||
{}
|
||||
|
||||
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 writeSync();
|
||||
|
||||
void getTrackFormat(IbmEncoderProto::TrackdataProto& format, unsigned track, unsigned side);
|
||||
|
||||
private:
|
||||
const IbmEncoderProto& _config;
|
||||
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
|
||||
|
||||
34
arch/ibm/ibm.proto
Normal file
34
arch/ibm/ibm.proto
Normal file
@@ -0,0 +1,34 @@
|
||||
syntax = "proto2";
|
||||
|
||||
import "lib/common.proto";
|
||||
|
||||
message IbmDecoderProto {
|
||||
optional int32 sector_id_base = 1 [default = 1, (help) = "ID of first sector"];
|
||||
optional bool ignore_side_byte = 2 [default = false, (help) = "ignore side byte in sector header"];
|
||||
optional RangeProto required_sectors = 3 [(help) = "require these sectors to exist for a good read"];
|
||||
}
|
||||
|
||||
message IbmEncoderProto {
|
||||
message TrackdataProto {
|
||||
optional int32 cylinder = 15 [(help) = "if set, the format applies only to this track"];
|
||||
optional int32 head = 16 [(help) = "if set, the format applies only to this head"];
|
||||
|
||||
optional double track_length_ms = 1 [(help) = "length of track"];
|
||||
optional int32 sector_size = 2 [default=512, (help) = "number of bytes per sector"];
|
||||
optional bool emit_iam = 3 [default=true, (help) = "whether to emit an IAM record"];
|
||||
optional int32 start_sector_id = 4 [default=1, (help) = "ID of first sector"];
|
||||
optional double clock_rate_khz = 5 [(help) = "data clock rate"];
|
||||
optional bool use_fm = 6 [default=false, (help) = "whether to use FM encoding rather than MFM"];
|
||||
optional int32 idam_byte = 7 [default=0x5554, (help) = "16-bit raw bit pattern of IDAM byte"];
|
||||
optional int32 dam_byte = 8 [default=0x5545, (help) = "16-bit raw bit pattern of DAM byte"];
|
||||
optional int32 gap0 = 9 [default=80, (help) = "size of gap 1 (the post-index gap)"];
|
||||
optional int32 gap1 = 10 [default=50, (help) = "size of gap 2 (the post-ID gap)"];
|
||||
optional int32 gap2 = 11 [default=22, (help) = "size of gap 3 (the pre-data gap)"];
|
||||
optional int32 gap3 = 12 [default=80, (help) = "size of gap 4 (the post-data or format gap)"];
|
||||
optional string sector_skew = 13 [(help) = "order to emit sectors"];
|
||||
optional bool swap_sides = 14 [default=false, (help) = "swap side bytes when writing"];
|
||||
}
|
||||
|
||||
repeated TrackdataProto trackdata = 1;
|
||||
}
|
||||
|
||||
@@ -118,10 +118,10 @@ static Bytes decode_crazy_data(const Bytes& input, Sector::Status& status)
|
||||
uint8_t decode_side(uint8_t side)
|
||||
{
|
||||
/* Mac disks, being weird, use the side byte to encode both the side (in
|
||||
* bit 5) and also whether we're above track 0x3f (in bit 6).
|
||||
* bit 5) and also whether we're above track 0x3f (in bit 0).
|
||||
*/
|
||||
|
||||
return !!(side & 0x40);
|
||||
return !!(side & 0x20);
|
||||
}
|
||||
|
||||
AbstractDecoder::RecordType MacintoshDecoder::advanceToNextRecord()
|
||||
@@ -180,5 +180,29 @@ void MacintoshDecoder::decodeDataRecord()
|
||||
inputbuffer[i] = decode_data_gcr(inputbuffer[i]);
|
||||
|
||||
_sector->status = Sector::BAD_CHECKSUM;
|
||||
_sector->data = decode_crazy_data(inputbuffer, _sector->status);
|
||||
Bytes userData = decode_crazy_data(inputbuffer, _sector->status);
|
||||
_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;
|
||||
while (count--)
|
||||
sectors.insert(count);
|
||||
return sectors;
|
||||
}
|
||||
|
||||
|
||||
|
||||
242
arch/macintosh/encoder.cc
Normal file
242
arch/macintosh/encoder.cc
Normal file
@@ -0,0 +1,242 @@
|
||||
#include "globals.h"
|
||||
#include "record.h"
|
||||
#include "decoders/decoders.h"
|
||||
#include "encoders/encoders.h"
|
||||
#include "macintosh.h"
|
||||
#include "crc.h"
|
||||
#include "sectorset.h"
|
||||
#include "writer.h"
|
||||
#include "fmt/format.h"
|
||||
#include <ctype.h>
|
||||
|
||||
FlagGroup macintoshEncoderFlags;
|
||||
|
||||
static DoubleFlag postIndexGapUs(
|
||||
{ "--post-index-gap-us" },
|
||||
"Post-index gap before first sector header (microseconds).",
|
||||
0);
|
||||
|
||||
static DoubleFlag clockCompensation(
|
||||
{ "--clock-compensation-factor" },
|
||||
"Scale the output clock by this much.",
|
||||
1.0);
|
||||
|
||||
static bool lastBit;
|
||||
|
||||
static double clockRateUsForTrack(unsigned track)
|
||||
{
|
||||
if (track < 16)
|
||||
return 2.623;
|
||||
if (track < 32)
|
||||
return 2.861;
|
||||
if (track < 48)
|
||||
return 3.148;
|
||||
if (track < 64)
|
||||
return 3.497;
|
||||
return 3.934;
|
||||
}
|
||||
|
||||
static unsigned sectorsForTrack(unsigned track)
|
||||
{
|
||||
if (track < 16)
|
||||
return 12;
|
||||
if (track < 32)
|
||||
return 11;
|
||||
if (track < 48)
|
||||
return 10;
|
||||
if (track < 64)
|
||||
return 9;
|
||||
return 8;
|
||||
}
|
||||
|
||||
static int encode_data_gcr(uint8_t gcr)
|
||||
{
|
||||
switch (gcr)
|
||||
{
|
||||
#define GCR_ENTRY(gcr, data) \
|
||||
case data: return gcr;
|
||||
#include "data_gcr.h"
|
||||
#undef GCR_ENTRY
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
|
||||
/* This is extremely inspired by the MESS implementation, written by Nathan Woods
|
||||
* and R. Belmont: https://github.com/mamedev/mame/blob/4263a71e64377db11392c458b580c5ae83556bc7/src/lib/formats/ap_dsk35.cpp
|
||||
*/
|
||||
static Bytes encode_crazy_data(const Bytes& input)
|
||||
{
|
||||
Bytes output;
|
||||
ByteWriter bw(output);
|
||||
ByteReader br(input);
|
||||
|
||||
uint8_t w1, w2, w3, w4;
|
||||
|
||||
static const int LOOKUP_LEN = MAC_SECTOR_LENGTH / 3;
|
||||
|
||||
uint8_t b1[LOOKUP_LEN + 1];
|
||||
uint8_t b2[LOOKUP_LEN + 1];
|
||||
uint8_t b3[LOOKUP_LEN + 1];
|
||||
|
||||
uint32_t c1 = 0;
|
||||
uint32_t c2 = 0;
|
||||
uint32_t c3 = 0;
|
||||
for (int j=0;; j++)
|
||||
{
|
||||
c1 = (c1 & 0xff) << 1;
|
||||
if (c1 & 0x0100)
|
||||
c1++;
|
||||
|
||||
uint8_t val = br.read_8();
|
||||
c3 += val;
|
||||
if (c1 & 0x0100)
|
||||
{
|
||||
c3++;
|
||||
c1 &= 0xff;
|
||||
}
|
||||
b1[j] = (val ^ c1) & 0xff;
|
||||
|
||||
val = br.read_8();
|
||||
c2 += val;
|
||||
if (c3 > 0xff)
|
||||
{
|
||||
c2++;
|
||||
c3 &= 0xff;
|
||||
}
|
||||
b2[j] = (val ^ c3) & 0xff;
|
||||
|
||||
if (br.pos == 524)
|
||||
break;
|
||||
|
||||
val = br.read_8();
|
||||
c1 += val;
|
||||
if (c2 > 0xff)
|
||||
{
|
||||
c1++;
|
||||
c2 &= 0xff;
|
||||
}
|
||||
b3[j] = (val ^ c2) & 0xff;
|
||||
}
|
||||
uint32_t c4 = ((c1 & 0xc0) >> 6) | ((c2 & 0xc0) >> 4) | ((c3 & 0xc0) >> 2);
|
||||
b3[LOOKUP_LEN] = 0;
|
||||
|
||||
for (int i = 0; i <= LOOKUP_LEN; i++)
|
||||
{
|
||||
w1 = b1[i] & 0x3f;
|
||||
w2 = b2[i] & 0x3f;
|
||||
w3 = b3[i] & 0x3f;
|
||||
w4 = ((b1[i] & 0xc0) >> 2);
|
||||
w4 |= ((b2[i] & 0xc0) >> 4);
|
||||
w4 |= ((b3[i] & 0xc0) >> 6);
|
||||
|
||||
bw.write_8(w4);
|
||||
bw.write_8(w1);
|
||||
bw.write_8(w2);
|
||||
|
||||
if (i != LOOKUP_LEN)
|
||||
bw.write_8(w3);
|
||||
}
|
||||
|
||||
bw.write_8(c4 & 0x3f);
|
||||
bw.write_8(c3 & 0x3f);
|
||||
bw.write_8(c2 & 0x3f);
|
||||
bw.write_8(c1 & 0x3f);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
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 uint8_t encode_side(uint8_t track, uint8_t side)
|
||||
{
|
||||
/* Mac disks, being weird, use the side byte to encode both the side (in
|
||||
* bit 5) and also whether we're above track 0x3f (in bit 0).
|
||||
*/
|
||||
|
||||
return (side ? 0x20 : 0x00) | ((track>0x3f) ? 0x01 : 0x00);
|
||||
}
|
||||
|
||||
static void write_sector(std::vector<bool>& bits, unsigned& cursor, const Sector* sector)
|
||||
{
|
||||
if ((sector->data.size() != 512) && (sector->data.size() != 524))
|
||||
Error() << "unsupported sector size --- you must pick 512 or 524";
|
||||
|
||||
write_bits(bits, cursor, 0xff, 1*8); /* pad byte */
|
||||
for (int i=0; i<7; i++)
|
||||
write_bits(bits, cursor, 0xff3fcff3fcffLL, 6*8); /* sync */
|
||||
write_bits(bits, cursor, MAC_SECTOR_RECORD, 3*8);
|
||||
|
||||
uint8_t encodedTrack = sector->physicalTrack & 0x3f;
|
||||
uint8_t encodedSector = sector->logicalSector;
|
||||
uint8_t encodedSide = encode_side(sector->physicalTrack, sector->logicalSide);
|
||||
uint8_t formatByte = MAC_FORMAT_BYTE;
|
||||
uint8_t headerChecksum = (encodedTrack ^ encodedSector ^ encodedSide ^ formatByte) & 0x3f;
|
||||
|
||||
write_bits(bits, cursor, encode_data_gcr(encodedTrack), 1*8);
|
||||
write_bits(bits, cursor, encode_data_gcr(encodedSector), 1*8);
|
||||
write_bits(bits, cursor, encode_data_gcr(encodedSide), 1*8);
|
||||
write_bits(bits, cursor, encode_data_gcr(formatByte), 1*8);
|
||||
write_bits(bits, cursor, encode_data_gcr(headerChecksum), 1*8);
|
||||
|
||||
write_bits(bits, cursor, 0xdeaaff, 3*8);
|
||||
write_bits(bits, cursor, 0xff3fcff3fcffLL, 6*8); /* sync */
|
||||
write_bits(bits, cursor, MAC_DATA_RECORD, 3*8);
|
||||
write_bits(bits, cursor, encode_data_gcr(sector->logicalSector), 1*8);
|
||||
|
||||
Bytes wireData;
|
||||
wireData.writer().append(sector->data.slice(512, 12)).append(sector->data.slice(0, 512));
|
||||
for (uint8_t b : encode_crazy_data(wireData))
|
||||
write_bits(bits, cursor, encode_data_gcr(b), 1*8);
|
||||
|
||||
write_bits(bits, cursor, 0xdeaaff, 3*8);
|
||||
}
|
||||
|
||||
std::unique_ptr<Fluxmap> MacintoshEncoder::encode(
|
||||
int physicalTrack, int physicalSide, const SectorSet& allSectors)
|
||||
{
|
||||
if ((physicalTrack < 0) || (physicalTrack >= MAC_TRACKS_PER_DISK))
|
||||
return std::unique_ptr<Fluxmap>();
|
||||
|
||||
double clockRateUs = clockRateUsForTrack(physicalTrack) * clockCompensation;
|
||||
int bitsPerRevolution = 200000.0 / clockRateUs;
|
||||
std::vector<bool> bits(bitsPerRevolution);
|
||||
unsigned cursor = 0;
|
||||
|
||||
fillBitmapTo(bits, cursor, postIndexGapUs / clockRateUs, { true, false });
|
||||
lastBit = false;
|
||||
|
||||
unsigned numSectors = sectorsForTrack(physicalTrack);
|
||||
for (int sectorId=0; sectorId<numSectors; sectorId++)
|
||||
{
|
||||
const auto& sectorData = allSectors.get(physicalTrack, physicalSide, sectorId);
|
||||
write_sector(bits, cursor, sectorData);
|
||||
}
|
||||
|
||||
if (cursor >= bits.size())
|
||||
Error() << fmt::format("track data overrun by {} bits", cursor - bits.size());
|
||||
fillBitmapTo(bits, cursor, bits.size(), { true, false });
|
||||
|
||||
std::unique_ptr<Fluxmap> fluxmap(new Fluxmap);
|
||||
fluxmap->appendBits(bits, clockRateUs*1e3);
|
||||
return fluxmap;
|
||||
}
|
||||
|
||||
@@ -1,24 +1,48 @@
|
||||
#ifndef MACINTOSH_H
|
||||
#define MACINTOSH_H
|
||||
|
||||
#include "decoders/decoders.h"
|
||||
#include "encoders/encoders.h"
|
||||
|
||||
#define MAC_SECTOR_RECORD 0xd5aa96 /* 1101 0101 1010 1010 1001 0110 */
|
||||
#define MAC_DATA_RECORD 0xd5aaad /* 1101 0101 1010 1010 1010 1101 */
|
||||
|
||||
#define MAC_SECTOR_LENGTH 524 /* yes, really */
|
||||
#define MAC_ENCODED_SECTOR_LENGTH 703
|
||||
#define MAC_FORMAT_BYTE 0x22
|
||||
|
||||
#define MAC_TRACKS_PER_DISK 80
|
||||
|
||||
class Sector;
|
||||
class Fluxmap;
|
||||
class MacintoshDecoderProto;
|
||||
class MacintoshEncoderProto;
|
||||
|
||||
class MacintoshDecoder : public AbstractDecoder
|
||||
{
|
||||
public:
|
||||
MacintoshDecoder(const MacintoshDecoderProto&) {}
|
||||
virtual ~MacintoshDecoder() {}
|
||||
|
||||
RecordType advanceToNextRecord();
|
||||
void decodeSectorRecord();
|
||||
void decodeDataRecord();
|
||||
|
||||
std::set<unsigned> requiredSectors(Track& track) const;
|
||||
};
|
||||
|
||||
class MacintoshEncoder : public AbstractEncoder
|
||||
{
|
||||
public:
|
||||
MacintoshEncoder(const MacintoshEncoderProto&) {}
|
||||
virtual ~MacintoshEncoder() {}
|
||||
|
||||
public:
|
||||
std::unique_ptr<Fluxmap> encode(int physicalTrack, int physicalSide, const SectorSet& allSectors);
|
||||
};
|
||||
|
||||
extern FlagGroup macintoshEncoderFlags;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
5
arch/macintosh/macintosh.proto
Normal file
5
arch/macintosh/macintosh.proto
Normal file
@@ -0,0 +1,5 @@
|
||||
syntax = "proto2";
|
||||
|
||||
message MacintoshDecoderProto {}
|
||||
message MacintoshEncoderProto {}
|
||||
|
||||
61
arch/micropolis/decoder.cc
Normal file
61
arch/micropolis/decoder.cc
Normal file
@@ -0,0 +1,61 @@
|
||||
#include "globals.h"
|
||||
#include "fluxmap.h"
|
||||
#include "decoders/fluxmapreader.h"
|
||||
#include "decoders/decoders.h"
|
||||
#include "sector.h"
|
||||
#include "micropolis.h"
|
||||
#include "bytes.h"
|
||||
#include "fmt/format.h"
|
||||
|
||||
/* The sector has a preamble of MFM 0x00s and uses 0xFF as a sync pattern. */
|
||||
static const FluxPattern SECTOR_SYNC_PATTERN(32, 0xaaaa5555);
|
||||
|
||||
AbstractDecoder::RecordType MicropolisDecoder::advanceToNextRecord()
|
||||
{
|
||||
_fmr->seekToIndexMark();
|
||||
const FluxMatcher* matcher = nullptr;
|
||||
_sector->clock = _fmr->seekToPattern(SECTOR_SYNC_PATTERN, matcher);
|
||||
if (matcher == &SECTOR_SYNC_PATTERN) {
|
||||
readRawBits(16);
|
||||
return SECTOR_RECORD;
|
||||
}
|
||||
return UNKNOWN_RECORD;
|
||||
}
|
||||
|
||||
/* Adds all bytes, with carry. */
|
||||
static uint8_t checksum(const Bytes& bytes) {
|
||||
ByteReader br(bytes);
|
||||
uint16_t sum = 0;
|
||||
while (!br.eof()) {
|
||||
if (sum > 0xFF) {
|
||||
sum -= 0x100 - 1;
|
||||
}
|
||||
sum += br.read_8();
|
||||
}
|
||||
/* The last carry is ignored */
|
||||
return sum & 0xFF;
|
||||
}
|
||||
|
||||
void MicropolisDecoder::decodeSectorRecord()
|
||||
{
|
||||
auto rawbits = readRawBits(MICROPOLIS_ENCODED_SECTOR_SIZE*16);
|
||||
auto bytes = decodeFmMfm(rawbits).slice(0, MICROPOLIS_ENCODED_SECTOR_SIZE);
|
||||
ByteReader br(bytes);
|
||||
|
||||
br.read_8(); /* sync */
|
||||
_sector->logicalTrack = br.read_8();
|
||||
_sector->logicalSide = _sector->physicalSide;
|
||||
_sector->logicalSector = br.read_8();
|
||||
if (_sector->logicalSector > 15)
|
||||
return;
|
||||
if (_sector->logicalTrack > 77)
|
||||
return;
|
||||
|
||||
br.read(10); /* OS data or padding */
|
||||
_sector->data = br.read(256);
|
||||
uint8_t wantChecksum = br.read_8();
|
||||
uint8_t gotChecksum = checksum(bytes.slice(1, 2+266));
|
||||
br.read(5); /* 4 byte ECC and ECC-present flag */
|
||||
|
||||
_sector->status = (wantChecksum == gotChecksum) ? Sector::OK : Sector::BAD_CHECKSUM;
|
||||
}
|
||||
20
arch/micropolis/micropolis.h
Normal file
20
arch/micropolis/micropolis.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef MICROPOLIS_H
|
||||
#define MICROPOLIS_H
|
||||
|
||||
#define MICROPOLIS_ENCODED_SECTOR_SIZE (1+2+266+6)
|
||||
|
||||
class Sector;
|
||||
class Fluxmap;
|
||||
class MicropolisDecoderProto;
|
||||
|
||||
class MicropolisDecoder : public AbstractDecoder
|
||||
{
|
||||
public:
|
||||
MicropolisDecoder(const MicropolisDecoderProto&) {}
|
||||
virtual ~MicropolisDecoder() {}
|
||||
|
||||
RecordType advanceToNextRecord();
|
||||
void decodeSectorRecord();
|
||||
};
|
||||
|
||||
#endif
|
||||
4
arch/micropolis/micropolis.proto
Normal file
4
arch/micropolis/micropolis.proto
Normal file
@@ -0,0 +1,4 @@
|
||||
syntax = "proto2";
|
||||
|
||||
message MicropolisDecoderProto {}
|
||||
|
||||
@@ -37,7 +37,7 @@ AbstractDecoder::RecordType MxDecoder::advanceToNextRecord()
|
||||
const FluxMatcher* matcher = nullptr;
|
||||
_sector->clock = _clock = _fmr->seekToPattern(ID_PATTERN, matcher);
|
||||
readRawBits(32); /* skip the ID mark */
|
||||
_logicalTrack = decodeFmMfm(readRawBits(32)).reader().read_be16();
|
||||
_logicalTrack = decodeFmMfm(readRawBits(32)).slice(0, 32).reader().read_be16();
|
||||
}
|
||||
else if (_currentSector == 10)
|
||||
{
|
||||
|
||||
@@ -3,9 +3,12 @@
|
||||
|
||||
#include "decoders/decoders.h"
|
||||
|
||||
class MxDecoderProto;
|
||||
|
||||
class MxDecoder : public AbstractDecoder
|
||||
{
|
||||
public:
|
||||
MxDecoder(const MxDecoderProto&) {}
|
||||
virtual ~MxDecoder() {}
|
||||
|
||||
void beginTrack();
|
||||
|
||||
4
arch/mx/mx.proto
Normal file
4
arch/mx/mx.proto
Normal file
@@ -0,0 +1,4 @@
|
||||
syntax = "proto2";
|
||||
|
||||
message MxDecoderProto {}
|
||||
|
||||
175
arch/northstar/decoder.cc
Normal file
175
arch/northstar/decoder.cc
Normal file
@@ -0,0 +1,175 @@
|
||||
/* Decoder for North Star 10-sector hard-sectored disks.
|
||||
*
|
||||
* Supports both single- and double-density. For the sector format and
|
||||
* checksum algorithm, see pp. 33 of the North Star Double Density Controller
|
||||
* manual:
|
||||
*
|
||||
* http://bitsavers.org/pdf/northstar/boards/Northstar_MDS-A-D_1978.pdf
|
||||
*
|
||||
* North Star disks do not contain any track/head/sector information
|
||||
* encoded in the sector record. For this reason, we have to be absolutely
|
||||
* sure that the hardSectorId is correct.
|
||||
*/
|
||||
|
||||
#include "globals.h"
|
||||
#include "fluxmap.h"
|
||||
#include "decoders/fluxmapreader.h"
|
||||
#include "decoders/decoders.h"
|
||||
#include "sector.h"
|
||||
#include "northstar.h"
|
||||
#include "bytes.h"
|
||||
#include "fmt/format.h"
|
||||
|
||||
/*
|
||||
* MFM sectors have 32 bytes of 00's followed by two sync characters,
|
||||
* specified in the North Star MDS manual as 0xFBFB.
|
||||
*
|
||||
* This is true for most disks; however, I found a few disks, including an
|
||||
* original North Star DOS/BASIC v2.2.1 DQ disk) that uses 0xFBnn, where
|
||||
* nn is an incrementing pattern.
|
||||
*
|
||||
* 00 00 00 F B
|
||||
* 0000 0000 0000 0000 0000 0000 0101 0101 0100 0101
|
||||
* A A A A A A 5 5 4 5
|
||||
*/
|
||||
static const FluxPattern MFM_PATTERN(64, 0xAAAAAAAAAAAA5545LL);
|
||||
|
||||
/* FM sectors have 16 bytes of 00's followed by 0xFB.
|
||||
* 00 FB
|
||||
* 0000 0000 1111 1111 1110 1111
|
||||
* A A F F E F
|
||||
*/
|
||||
static const FluxPattern FM_PATTERN(64, 0xAAAAAAAAAAAAFFEFLL);
|
||||
|
||||
const FluxMatchers ANY_SECTOR_PATTERN(
|
||||
{
|
||||
&MFM_PATTERN,
|
||||
&FM_PATTERN,
|
||||
}
|
||||
);
|
||||
|
||||
/* Search for FM or MFM sector record */
|
||||
AbstractDecoder::RecordType NorthstarDecoder::advanceToNextRecord()
|
||||
{
|
||||
nanoseconds_t now = _fmr->tell().ns();
|
||||
|
||||
/* For all but the first sector, seek to the next sector pulse.
|
||||
* The first sector does not contain the sector pulse in the fluxmap.
|
||||
*/
|
||||
if (now != 0) {
|
||||
_fmr->seekToIndexMark();
|
||||
now = _fmr->tell().ns();
|
||||
}
|
||||
|
||||
/* Discard a possible partial sector at the end of the track.
|
||||
* This partial sector could be mistaken for a conflicted sector, if
|
||||
* whatever data read happens to match the checksum of 0, which is
|
||||
* rare, but has been observed on some disks.
|
||||
*/
|
||||
if (now > (_fmr->getDuration() - 21e6)) {
|
||||
_fmr->seekToIndexMark();
|
||||
return(UNKNOWN_RECORD);
|
||||
}
|
||||
|
||||
int msSinceIndex = std::round(now / 1e6);
|
||||
|
||||
const FluxMatcher* matcher = nullptr;
|
||||
|
||||
/* Note that the seekToPattern ignores the sector pulses, so if
|
||||
* a sector is not found for some reason, the seek will advance
|
||||
* past one or more sector pulses. For this reason, calculate
|
||||
* _hardSectorId after the sector header is found.
|
||||
*/
|
||||
_sector->clock = _fmr->seekToPattern(ANY_SECTOR_PATTERN, matcher);
|
||||
|
||||
int sectorFoundTimeRaw = std::round((_fmr->tell().ns()) / 1e6);
|
||||
int sectorFoundTime;
|
||||
|
||||
/* Round time to the nearest 20ms */
|
||||
if ((sectorFoundTimeRaw % 20) < 10) {
|
||||
sectorFoundTime = (sectorFoundTimeRaw / 20) * 20;
|
||||
}
|
||||
else {
|
||||
sectorFoundTime = ((sectorFoundTimeRaw + 20) / 20) * 20;
|
||||
}
|
||||
|
||||
/* Calculate the sector ID based on time since the index */
|
||||
_hardSectorId = (sectorFoundTime / 20) % 10;
|
||||
|
||||
// std::cout << fmt::format(
|
||||
// "Sector ID {}: hole at {}ms, sector start at {}ms",
|
||||
// _hardSectorId, msSinceIndex, sectorFoundTimeRaw) << std::endl;
|
||||
|
||||
if (matcher == &MFM_PATTERN) {
|
||||
_sectorType = SECTOR_TYPE_MFM;
|
||||
readRawBits(48);
|
||||
return SECTOR_RECORD;
|
||||
}
|
||||
|
||||
if (matcher == &FM_PATTERN) {
|
||||
_sectorType = SECTOR_TYPE_FM;
|
||||
readRawBits(48);
|
||||
return SECTOR_RECORD;
|
||||
}
|
||||
|
||||
return UNKNOWN_RECORD;
|
||||
}
|
||||
|
||||
/* Checksum is initially 0.
|
||||
* For each data byte, XOR with the current checksum.
|
||||
* Rotate checksum left, carrying bit 7 to bit 0.
|
||||
*/
|
||||
uint8_t northstarChecksum(const Bytes& bytes) {
|
||||
ByteReader br(bytes);
|
||||
uint8_t checksum = 0;
|
||||
|
||||
while (!br.eof()) {
|
||||
checksum ^= br.read_8();
|
||||
checksum = ((checksum << 1) | ((checksum >> 7)));
|
||||
}
|
||||
|
||||
return checksum;
|
||||
}
|
||||
|
||||
void NorthstarDecoder::decodeSectorRecord()
|
||||
{
|
||||
unsigned recordSize, payloadSize, headerSize;
|
||||
|
||||
if (_sectorType == SECTOR_TYPE_MFM) {
|
||||
recordSize = NORTHSTAR_ENCODED_SECTOR_SIZE_DD;
|
||||
payloadSize = NORTHSTAR_PAYLOAD_SIZE_DD;
|
||||
headerSize = NORTHSTAR_HEADER_SIZE_DD;
|
||||
}
|
||||
else {
|
||||
recordSize = NORTHSTAR_ENCODED_SECTOR_SIZE_SD;
|
||||
payloadSize = NORTHSTAR_PAYLOAD_SIZE_SD;
|
||||
headerSize = NORTHSTAR_HEADER_SIZE_SD;
|
||||
}
|
||||
|
||||
auto rawbits = readRawBits(recordSize * 16);
|
||||
auto bytes = decodeFmMfm(rawbits).slice(0, recordSize);
|
||||
ByteReader br(bytes);
|
||||
uint8_t sync_char;
|
||||
|
||||
_sector->logicalSide = _sector->physicalSide;
|
||||
_sector->logicalSector = _hardSectorId;
|
||||
_sector->logicalTrack = _sector->physicalTrack;
|
||||
|
||||
sync_char = br.read_8(); /* Sync char: 0xFB */
|
||||
if (_sectorType == SECTOR_TYPE_MFM) {
|
||||
sync_char = br.read_8();/* MFM second Sync char, usually 0xFB */
|
||||
}
|
||||
|
||||
_sector->data = br.read(payloadSize);
|
||||
|
||||
uint8_t wantChecksum = br.read_8();
|
||||
uint8_t gotChecksum = northstarChecksum(bytes.slice(headerSize, payloadSize));
|
||||
|
||||
_sector->status = (wantChecksum == gotChecksum) ? Sector::OK : Sector::BAD_CHECKSUM;
|
||||
}
|
||||
|
||||
std::set<unsigned> NorthstarDecoder::requiredSectors(Track& track) const
|
||||
{
|
||||
static std::set<unsigned> sectors = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
|
||||
return sectors;
|
||||
}
|
||||
130
arch/northstar/encoder.cc
Normal file
130
arch/northstar/encoder.cc
Normal file
@@ -0,0 +1,130 @@
|
||||
#include "globals.h"
|
||||
#include "northstar.h"
|
||||
#include "sectorset.h"
|
||||
|
||||
#define GAP_FILL_SIZE_SD 30
|
||||
#define PRE_HEADER_GAP_FILL_SIZE_SD 9
|
||||
#define GAP_FILL_SIZE_DD 62
|
||||
#define PRE_HEADER_GAP_FILL_SIZE_DD 16
|
||||
|
||||
#define GAP1_FILL_BYTE (0x4F)
|
||||
#define GAP2_FILL_BYTE (0x4F)
|
||||
|
||||
#define TOTAL_SECTOR_BYTES ()
|
||||
|
||||
static void write_sector(std::vector<bool>& bits, unsigned& cursor, const Sector* sector)
|
||||
{
|
||||
int preambleSize = 0;
|
||||
int encodedSectorSize = 0;
|
||||
int gapFillSize = 0;
|
||||
int preHeaderGapFillSize = 0;
|
||||
|
||||
bool doubleDensity;
|
||||
|
||||
switch (sector->data.size()) {
|
||||
case NORTHSTAR_PAYLOAD_SIZE_SD:
|
||||
preambleSize = NORTHSTAR_PREAMBLE_SIZE_SD;
|
||||
encodedSectorSize = PRE_HEADER_GAP_FILL_SIZE_SD + NORTHSTAR_ENCODED_SECTOR_SIZE_SD + GAP_FILL_SIZE_SD;
|
||||
gapFillSize = GAP_FILL_SIZE_SD;
|
||||
preHeaderGapFillSize = PRE_HEADER_GAP_FILL_SIZE_SD;
|
||||
doubleDensity = false;
|
||||
break;
|
||||
case NORTHSTAR_PAYLOAD_SIZE_DD:
|
||||
preambleSize = NORTHSTAR_PREAMBLE_SIZE_DD;
|
||||
encodedSectorSize = PRE_HEADER_GAP_FILL_SIZE_DD + NORTHSTAR_ENCODED_SECTOR_SIZE_DD + GAP_FILL_SIZE_DD;
|
||||
gapFillSize = GAP_FILL_SIZE_DD;
|
||||
preHeaderGapFillSize = PRE_HEADER_GAP_FILL_SIZE_DD;
|
||||
doubleDensity = true;
|
||||
break;
|
||||
default:
|
||||
Error() << "unsupported sector size --- you must pick 256 or 512";
|
||||
break;
|
||||
}
|
||||
|
||||
int fullSectorSize = preambleSize + encodedSectorSize;
|
||||
auto fullSector = std::make_shared<std::vector<uint8_t>>();
|
||||
fullSector->reserve(fullSectorSize);
|
||||
|
||||
/* sector gap after index pulse */
|
||||
for (int i = 0; i < preHeaderGapFillSize; i++)
|
||||
fullSector->push_back(GAP1_FILL_BYTE);
|
||||
|
||||
/* sector preamble */
|
||||
for (int i = 0; i < preambleSize; i++)
|
||||
fullSector->push_back(0);
|
||||
|
||||
Bytes sectorData;
|
||||
if (sector->data.size() == encodedSectorSize)
|
||||
sectorData = sector->data;
|
||||
else {
|
||||
ByteWriter writer(sectorData);
|
||||
writer.write_8(0xFB); /* sync character */
|
||||
if (doubleDensity == true) {
|
||||
writer.write_8(0xFB); /* Double-density has two sync characters */
|
||||
}
|
||||
writer += sector->data;
|
||||
if (doubleDensity == true) {
|
||||
writer.write_8(northstarChecksum(sectorData.slice(2)));
|
||||
} else {
|
||||
writer.write_8(northstarChecksum(sectorData.slice(1)));
|
||||
}
|
||||
}
|
||||
for (uint8_t b : sectorData)
|
||||
fullSector->push_back(b);
|
||||
|
||||
if (sector->logicalSector != 9) {
|
||||
/* sector postamble */
|
||||
for (int i = 0; i < gapFillSize; i++)
|
||||
fullSector->push_back(GAP2_FILL_BYTE);
|
||||
|
||||
if (fullSector->size() != fullSectorSize)
|
||||
Error() << "sector mismatched length (" << sector->data.size() << ") expected: " << fullSector->size() << " got " << fullSectorSize;
|
||||
} else {
|
||||
/* sector postamble */
|
||||
for (int i = 0; i < gapFillSize; i++)
|
||||
fullSector->push_back(GAP2_FILL_BYTE);
|
||||
}
|
||||
|
||||
bool lastBit = false;
|
||||
|
||||
if (doubleDensity == true) {
|
||||
encodeMfm(bits, cursor, fullSector, lastBit);
|
||||
}
|
||||
else {
|
||||
encodeFm(bits, cursor, fullSector);
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<Fluxmap> NorthstarEncoder::encode(
|
||||
int physicalTrack, int physicalSide, const SectorSet& allSectors)
|
||||
{
|
||||
int bitsPerRevolution = 100000;
|
||||
double clockRateUs = 4.00;
|
||||
|
||||
if ((physicalTrack < 0) || (physicalTrack >= 35))
|
||||
return std::unique_ptr<Fluxmap>();
|
||||
|
||||
const auto& sector = allSectors.get(physicalTrack, physicalSide, 0);
|
||||
|
||||
if (sector->data.size() == NORTHSTAR_PAYLOAD_SIZE_SD) {
|
||||
bitsPerRevolution /= 2; // FM
|
||||
} else {
|
||||
clockRateUs /= 2.00;
|
||||
}
|
||||
|
||||
std::vector<bool> bits(bitsPerRevolution);
|
||||
unsigned cursor = 0;
|
||||
|
||||
for (int sectorId = 0; sectorId < 10; sectorId++)
|
||||
{
|
||||
const auto& sectorData = allSectors.get(physicalTrack, physicalSide, sectorId);
|
||||
write_sector(bits, cursor, sectorData);
|
||||
}
|
||||
|
||||
if (cursor > bits.size())
|
||||
Error() << "track data overrun";
|
||||
|
||||
std::unique_ptr<Fluxmap> fluxmap(new Fluxmap);
|
||||
fluxmap->appendBits(bits, clockRateUs * 1e3);
|
||||
return fluxmap;
|
||||
}
|
||||
72
arch/northstar/northstar.h
Normal file
72
arch/northstar/northstar.h
Normal file
@@ -0,0 +1,72 @@
|
||||
#ifndef NORTHSTAR_H
|
||||
#define NORTHSTAR_H
|
||||
|
||||
/* Northstar floppies are 10-hard sectored disks with a sector format as follows:
|
||||
*
|
||||
* |----------------------------------|
|
||||
* | SYNC Byte | Payload | Checksum |
|
||||
* |------------+----------+----------|
|
||||
* | 1 (0xFB) | 256 (SD) | 1 |
|
||||
* | 2 (0xFBFB) | 512 (DD) | |
|
||||
* |----------------------------------|
|
||||
*
|
||||
*/
|
||||
|
||||
#include "decoders/decoders.h"
|
||||
#include "encoders/encoders.h"
|
||||
|
||||
#define NORTHSTAR_PREAMBLE_SIZE_SD (16)
|
||||
#define NORTHSTAR_PREAMBLE_SIZE_DD (32)
|
||||
#define NORTHSTAR_HEADER_SIZE_SD (1)
|
||||
#define NORTHSTAR_HEADER_SIZE_DD (2)
|
||||
#define NORTHSTAR_PAYLOAD_SIZE_SD (256)
|
||||
#define NORTHSTAR_PAYLOAD_SIZE_DD (512)
|
||||
#define NORTHSTAR_CHECKSUM_SIZE (1)
|
||||
#define NORTHSTAR_ENCODED_SECTOR_SIZE_SD (NORTHSTAR_HEADER_SIZE_SD + NORTHSTAR_PAYLOAD_SIZE_SD + NORTHSTAR_CHECKSUM_SIZE)
|
||||
#define NORTHSTAR_ENCODED_SECTOR_SIZE_DD (NORTHSTAR_HEADER_SIZE_DD + NORTHSTAR_PAYLOAD_SIZE_DD + NORTHSTAR_CHECKSUM_SIZE)
|
||||
|
||||
#define SECTOR_TYPE_MFM (0)
|
||||
#define SECTOR_TYPE_FM (1)
|
||||
|
||||
class NorthstarEncoderProto;
|
||||
class NorthstarDecoderProto;
|
||||
|
||||
class NorthstarDecoder : public AbstractDecoder
|
||||
{
|
||||
public:
|
||||
NorthstarDecoder(const NorthstarDecoderProto& config):
|
||||
_config(config)
|
||||
{
|
||||
_sectorType = SECTOR_TYPE_MFM;
|
||||
}
|
||||
|
||||
virtual ~NorthstarDecoder() {}
|
||||
|
||||
RecordType advanceToNextRecord();
|
||||
void decodeSectorRecord();
|
||||
std::set<unsigned> requiredSectors(Track& track) const;
|
||||
|
||||
private:
|
||||
const NorthstarDecoderProto& _config;
|
||||
uint8_t _sectorType;
|
||||
uint8_t _hardSectorId;
|
||||
};
|
||||
|
||||
class NorthstarEncoder : public AbstractEncoder
|
||||
{
|
||||
public:
|
||||
NorthstarEncoder(const NorthstarEncoderProto& config):
|
||||
_config(config)
|
||||
{}
|
||||
|
||||
virtual ~NorthstarEncoder() {}
|
||||
std::unique_ptr<Fluxmap> encode(int physicalTrack, int physicalSide, const SectorSet& allSectors);
|
||||
|
||||
private:
|
||||
const NorthstarEncoderProto& _config;
|
||||
};
|
||||
|
||||
extern FlagGroup northstarEncoderFlags;
|
||||
extern uint8_t northstarChecksum(const Bytes& bytes);
|
||||
|
||||
#endif /* NORTHSTAR */
|
||||
5
arch/northstar/northstar.proto
Normal file
5
arch/northstar/northstar.proto
Normal file
@@ -0,0 +1,5 @@
|
||||
syntax = "proto2";
|
||||
|
||||
message NorthstarDecoderProto {}
|
||||
message NorthstarEncoderProto {}
|
||||
|
||||
87
arch/tids990/decoder.cc
Normal file
87
arch/tids990/decoder.cc
Normal file
@@ -0,0 +1,87 @@
|
||||
#include "globals.h"
|
||||
#include "decoders/decoders.h"
|
||||
#include "encoders/encoders.h"
|
||||
#include "tids990/tids990.h"
|
||||
#include "crc.h"
|
||||
#include "fluxmap.h"
|
||||
#include "decoders/fluxmapreader.h"
|
||||
#include "sector.h"
|
||||
#include "record.h"
|
||||
#include "track.h"
|
||||
#include <string.h>
|
||||
#include <fmt/format.h>
|
||||
|
||||
/* The Texas Instruments DS990 uses MFM with a scheme similar to a simplified
|
||||
* version of the IBM record scheme (it's actually easier to parse than IBM).
|
||||
* There are 26 sectors per track, each holding a rather weird 288 bytes.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Sector record:
|
||||
* data: 0 1 0 1 0 1 0 1 .0 0 0 0 1 0 1 0 = 0x550a
|
||||
* mfm: 00 01 00 01 00 01 00 01.00 10 10 10 01 00 01 00 = 0x11112a44
|
||||
* special: 00 01 00 01 00 01 00 01.00 10 00 10 01 00 01 00 = 0x11112244
|
||||
* ^^
|
||||
* 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.
|
||||
*/
|
||||
const FluxPattern SECTOR_RECORD_PATTERN(32, 0x11112244);
|
||||
|
||||
/*
|
||||
* Data record:
|
||||
* data: 0 1 0 1 0 1 0 1 .0 0 0 0 1 0 1 1 = 0x550c
|
||||
* mfm: 00 01 00 01 00 01 00 01.00 10 10 10 01 00 01 01 = 0x11112a45
|
||||
* special: 00 01 00 01 00 01 00 01.00 10 00 10 01 00 01 01 = 0x11112245
|
||||
* ^^
|
||||
* 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.
|
||||
*/
|
||||
const FluxPattern DATA_RECORD_PATTERN(32, 0x11112245);
|
||||
|
||||
const FluxMatchers ANY_RECORD_PATTERN({ &SECTOR_RECORD_PATTERN, &DATA_RECORD_PATTERN });
|
||||
|
||||
AbstractDecoder::RecordType Tids990Decoder::advanceToNextRecord()
|
||||
{
|
||||
const FluxMatcher* matcher = nullptr;
|
||||
_sector->clock = _fmr->seekToPattern(ANY_RECORD_PATTERN, matcher);
|
||||
if (matcher == &SECTOR_RECORD_PATTERN)
|
||||
return RecordType::SECTOR_RECORD;
|
||||
if (matcher == &DATA_RECORD_PATTERN)
|
||||
return RecordType::DATA_RECORD;
|
||||
return RecordType::UNKNOWN_RECORD;
|
||||
}
|
||||
|
||||
void Tids990Decoder::decodeSectorRecord()
|
||||
{
|
||||
auto bits = readRawBits(TIDS990_SECTOR_RECORD_SIZE*16);
|
||||
auto bytes = decodeFmMfm(bits).slice(0, TIDS990_SECTOR_RECORD_SIZE);
|
||||
|
||||
ByteReader br(bytes);
|
||||
uint16_t gotChecksum = crc16(CCITT_POLY, bytes.slice(1, TIDS990_SECTOR_RECORD_SIZE-3));
|
||||
|
||||
br.seek(2);
|
||||
_sector->logicalSide = br.read_8() >> 3;
|
||||
_sector->logicalTrack = br.read_8();
|
||||
br.read_8(); /* number of sectors per track */
|
||||
_sector->logicalSector = br.read_8();
|
||||
br.read_be16(); /* sector size */
|
||||
uint16_t wantChecksum = br.read_be16();
|
||||
|
||||
if (wantChecksum == gotChecksum)
|
||||
_sector->status = Sector::DATA_MISSING; /* correct but unintuitive */
|
||||
}
|
||||
|
||||
void Tids990Decoder::decodeDataRecord()
|
||||
{
|
||||
auto bits = readRawBits(TIDS990_DATA_RECORD_SIZE*16);
|
||||
auto bytes = decodeFmMfm(bits).slice(0, TIDS990_DATA_RECORD_SIZE);
|
||||
|
||||
ByteReader br(bytes);
|
||||
uint16_t gotChecksum = crc16(CCITT_POLY, bytes.slice(1, TIDS990_DATA_RECORD_SIZE-3));
|
||||
|
||||
br.seek(2);
|
||||
_sector->data = br.read(TIDS990_PAYLOAD_SIZE);
|
||||
uint16_t wantChecksum = br.read_be16();
|
||||
_sector->status = (wantChecksum == gotChecksum) ? Sector::OK : Sector::BAD_CHECKSUM;
|
||||
}
|
||||
|
||||
130
arch/tids990/encoder.cc
Normal file
130
arch/tids990/encoder.cc
Normal file
@@ -0,0 +1,130 @@
|
||||
#include "globals.h"
|
||||
#include "record.h"
|
||||
#include "decoders/decoders.h"
|
||||
#include "encoders/encoders.h"
|
||||
#include "tids990.h"
|
||||
#include "crc.h"
|
||||
#include "sectorset.h"
|
||||
#include "writer.h"
|
||||
#include "arch/tids990/tids990.pb.h"
|
||||
#include <fmt/format.h>
|
||||
|
||||
static int charToInt(char c)
|
||||
{
|
||||
if (isdigit(c))
|
||||
return c - '0';
|
||||
return 10 + tolower(c) - 'a';
|
||||
}
|
||||
|
||||
void Tids990Encoder::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 Tids990Encoder::writeBytes(const Bytes& bytes)
|
||||
{
|
||||
encodeMfm(_bits, _cursor, bytes, _lastBit);
|
||||
}
|
||||
|
||||
void Tids990Encoder::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> Tids990Encoder::encode(
|
||||
int physicalTrack, int physicalSide, const SectorSet& allSectors)
|
||||
{
|
||||
double clockRateUs = 1e3 / _config.clock_rate_khz() / 2.0;
|
||||
int bitsPerRevolution = (_config.track_length_ms() * 1000.0) / clockRateUs;
|
||||
_bits.resize(bitsPerRevolution);
|
||||
_cursor = 0;
|
||||
|
||||
uint8_t am1Unencoded = decodeUint16(_config.am1_byte());
|
||||
uint8_t am2Unencoded = decodeUint16(_config.am2_byte());
|
||||
|
||||
writeBytes(_config.gap1_bytes(), 0x55);
|
||||
|
||||
bool first = true;
|
||||
for (char sectorChar : _config.sector_skew())
|
||||
{
|
||||
int sectorId = charToInt(sectorChar);
|
||||
if (!first)
|
||||
writeBytes(_config.gap3_bytes(), 0x55);
|
||||
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(12, 0x55);
|
||||
bw.write_8(am1Unencoded);
|
||||
bw.write_8(sectorData->logicalSide << 3);
|
||||
bw.write_8(sectorData->logicalTrack);
|
||||
bw.write_8(_config.sector_count());
|
||||
bw.write_8(sectorData->logicalSector);
|
||||
bw.write_be16(sectorData->data.size());
|
||||
uint16_t crc = crc16(CCITT_POLY, header);
|
||||
bw.write_be16(crc);
|
||||
|
||||
writeRawBits(_config.am1_byte(), 16);
|
||||
writeBytes(header.slice(1));
|
||||
}
|
||||
|
||||
writeBytes(_config.gap2_bytes(), 0x55);
|
||||
|
||||
{
|
||||
Bytes data;
|
||||
ByteWriter bw(data);
|
||||
|
||||
writeBytes(12, 0x55);
|
||||
bw.write_8(am2Unencoded);
|
||||
|
||||
bw += sectorData->data;
|
||||
uint16_t crc = crc16(CCITT_POLY, data);
|
||||
bw.write_be16(crc);
|
||||
|
||||
writeRawBits(_config.am2_byte(), 16);
|
||||
writeBytes(data.slice(1));
|
||||
}
|
||||
}
|
||||
|
||||
if (_cursor >= _bits.size())
|
||||
Error() << "track data overrun";
|
||||
while (_cursor < _bits.size())
|
||||
writeBytes(1, 0x55);
|
||||
|
||||
std::unique_ptr<Fluxmap> fluxmap(new Fluxmap);
|
||||
fluxmap->appendBits(_bits, clockRateUs*1e3);
|
||||
return fluxmap;
|
||||
}
|
||||
|
||||
54
arch/tids990/tids990.h
Normal file
54
arch/tids990/tids990.h
Normal file
@@ -0,0 +1,54 @@
|
||||
#ifndef TIDS990_H
|
||||
#define TIDS990_H
|
||||
|
||||
#define TIDS990_PAYLOAD_SIZE 288 /* bytes */
|
||||
#define TIDS990_SECTOR_RECORD_SIZE 10 /* bytes */
|
||||
#define TIDS990_DATA_RECORD_SIZE (TIDS990_PAYLOAD_SIZE + 4) /* bytes */
|
||||
|
||||
class Sector;
|
||||
class SectorSet;
|
||||
class Fluxmap;
|
||||
class Track;
|
||||
class Tids990DecoderProto;
|
||||
class Tids990EncoderProto;
|
||||
|
||||
class Tids990Decoder : public AbstractDecoder
|
||||
{
|
||||
public:
|
||||
Tids990Decoder(const Tids990DecoderProto&) {}
|
||||
virtual ~Tids990Decoder() {}
|
||||
|
||||
RecordType advanceToNextRecord();
|
||||
void decodeSectorRecord();
|
||||
void decodeDataRecord();
|
||||
};
|
||||
|
||||
class Tids990Encoder : public AbstractEncoder
|
||||
{
|
||||
public:
|
||||
Tids990Encoder(const Tids990EncoderProto& config):
|
||||
_config(config)
|
||||
{}
|
||||
virtual ~Tids990Encoder() {}
|
||||
|
||||
private:
|
||||
void writeRawBits(uint32_t data, int width);
|
||||
void writeBytes(const Bytes& bytes);
|
||||
void writeBytes(int count, uint8_t value);
|
||||
void writeSync();
|
||||
|
||||
public:
|
||||
std::unique_ptr<Fluxmap> encode(int physicalTrack, int physicalSide, const SectorSet& allSectors);
|
||||
|
||||
private:
|
||||
const Tids990EncoderProto& _config;
|
||||
std::vector<bool> _bits;
|
||||
unsigned _cursor;
|
||||
bool _lastBit;
|
||||
};
|
||||
|
||||
extern FlagGroup tids990EncoderFlags;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
26
arch/tids990/tids990.proto
Normal file
26
arch/tids990/tids990.proto
Normal file
@@ -0,0 +1,26 @@
|
||||
syntax = "proto2";
|
||||
|
||||
import "lib/common.proto";
|
||||
|
||||
message Tids990DecoderProto {}
|
||||
message Tids990EncoderProto {
|
||||
optional double track_length_ms = 1 [ default = 166,
|
||||
(help) = "length of a track" ];
|
||||
optional int32 sector_count = 2 [ default = 26,
|
||||
(help) = "number of sectors per track" ];
|
||||
optional double clock_rate_khz = 3 [ default = 500,
|
||||
(help) = "clock rate of data to write" ];
|
||||
optional int32 am1_byte = 4 [ default = 0x2244,
|
||||
(help) = "16-bit RAW bit pattern to use for the AM1 ID byte" ];
|
||||
optional int32 am2_byte = 5 [ default = 0x2245,
|
||||
(help) = "16-bit RAW bit pattern to use for the AM2 ID byte" ];
|
||||
optional int32 gap1_bytes = 6 [ default = 80,
|
||||
(help) = "size of gap 1 (the post-index gap)" ];
|
||||
optional int32 gap2_bytes = 7 [ default = 21,
|
||||
(help) = "size of gap 2 (the post-ID gap)" ];
|
||||
optional int32 gap3_bytes = 8 [ default = 51,
|
||||
(help) = "size of gap 3 (the post-data or format gap)" ];
|
||||
optional string sector_skew = 9 [ default = "1mhc72nid83oje94pkfa50lgb6",
|
||||
(help) = "order to emit sectors" ];
|
||||
}
|
||||
|
||||
@@ -8,10 +8,12 @@
|
||||
|
||||
class Sector;
|
||||
class Fluxmap;
|
||||
class Victor9kDecoderProto;
|
||||
|
||||
class Victor9kDecoder : public AbstractDecoder
|
||||
{
|
||||
public:
|
||||
Victor9kDecoder(const Victor9kDecoderProto&) {}
|
||||
virtual ~Victor9kDecoder() {}
|
||||
|
||||
RecordType advanceToNextRecord();
|
||||
|
||||
4
arch/victor9k/victor9k.proto
Normal file
4
arch/victor9k/victor9k.proto
Normal file
@@ -0,0 +1,4 @@
|
||||
syntax = "proto2";
|
||||
|
||||
message Victor9kDecoderProto {}
|
||||
|
||||
@@ -3,10 +3,12 @@
|
||||
|
||||
class Sector;
|
||||
class Fluxmap;
|
||||
class ZilogMczDecoderProto;
|
||||
|
||||
class ZilogMczDecoder : public AbstractDecoder
|
||||
{
|
||||
public:
|
||||
ZilogMczDecoder(const ZilogMczDecoderProto&) {}
|
||||
virtual ~ZilogMczDecoder() {}
|
||||
|
||||
RecordType advanceToNextRecord();
|
||||
|
||||
4
arch/zilogmcz/zilogmcz.proto
Normal file
4
arch/zilogmcz/zilogmcz.proto
Normal file
@@ -0,0 +1,4 @@
|
||||
syntax = "proto2";
|
||||
|
||||
message ZilogMczDecoderProto {}
|
||||
|
||||
2
dep/agg/AUTHORS
Normal file
2
dep/agg/AUTHORS
Normal file
@@ -0,0 +1,2 @@
|
||||
Anti-Grain Geometry - Version 2.4
|
||||
Copyright (C) 2002-2005 Maxim Shemanarev (McSeem)
|
||||
63
dep/agg/README
Normal file
63
dep/agg/README
Normal file
@@ -0,0 +1,63 @@
|
||||
The Anti-Grain Geometry Project
|
||||
A high quality rendering engine for C++
|
||||
http://antigrain.com
|
||||
|
||||
Anti-Grain Geometry - Version 2.4
|
||||
Copyright (C) 2002-2005 Maxim Shemanarev (McSeem)
|
||||
|
||||
Permission to copy, use, modify, sell and distribute this software
|
||||
is granted provided this copyright notice appears in all copies.
|
||||
This software is provided "as is" without express or implied
|
||||
warranty, and with no claim as to its suitability for any purpose.
|
||||
|
||||
---------------------------------
|
||||
|
||||
Use automake to build the library.
|
||||
|
||||
If automake is not available you still can use the old make.
|
||||
There is a very simple Makefile that can be used. Note that
|
||||
if you use automake it will overwrite Makefile.
|
||||
|
||||
---------------------------------
|
||||
|
||||
If building on AmigaOS 4.0 or higher type the following for
|
||||
instructions on what targets are available.
|
||||
make -f Makefile.AmigaOS
|
||||
|
||||
To just build and install AGG into the standard AmigaOS SDK
|
||||
ready for use type:
|
||||
make -f Makefile.AmigaOS install
|
||||
|
||||
If you just want to build one demo (e.g. lion) use:
|
||||
make -f Makefile.AmigaOS bin/lion
|
||||
|
||||
If you have any questions about the AmigaOS port please
|
||||
contact Steven Solie (ssolie@telus.net) for help.
|
||||
|
||||
---------------------------------
|
||||
|
||||
To build all examples using SDL (Mac or Linux) just type:
|
||||
|
||||
cd /examples/sdl
|
||||
make
|
||||
|
||||
Individual examples can be built with
|
||||
|
||||
make aa_test
|
||||
|
||||
In the same way the native Carbon examples can be built with
|
||||
|
||||
cd /examples/macosx_carbon
|
||||
make
|
||||
|
||||
In both cases the static library will be built (if it was not already)
|
||||
from the existing global Makefile in /src/.
|
||||
|
||||
The Makefiles for both SDL and Carbon will also attempt to download the
|
||||
required .bmp files if they are not found in the system for a given
|
||||
example. If the files could not be fetched (wget) the user will receive
|
||||
a message explaining where to download the samples from (sphere.bmp,
|
||||
etc.) Since all programs reside in the same directory there is no need
|
||||
to duplicate the .bmp files for each program that needs to use them.
|
||||
|
||||
---------------------------------
|
||||
7
dep/agg/README.md
Normal file
7
dep/agg/README.md
Normal file
@@ -0,0 +1,7 @@
|
||||
This is a vary stripped down copy of the Anti-Grain Antialiasing graphics
|
||||
rendering library --- I've removed all the platform-specific and control stuff
|
||||
so that it can be used to generate memory images only.
|
||||
|
||||
The original AGG site is dead, so this version is cloned from
|
||||
https://github.com/NNemec/antigrain.
|
||||
|
||||
7
dep/agg/UPSTREAM.md
Normal file
7
dep/agg/UPSTREAM.md
Normal file
@@ -0,0 +1,7 @@
|
||||
This is a vary stripped down copy of the Anti-Grain Antialiasing graphics
|
||||
rendering library --- I've removed all the platform-specific and control stuff
|
||||
so that it can be used to generate memory images only.
|
||||
|
||||
The original AGG site is dead, so this version is cloned from
|
||||
https://github.com/NNemec/antigrain.
|
||||
|
||||
49
dep/agg/include/Makefile.am
Normal file
49
dep/agg/include/Makefile.am
Normal file
@@ -0,0 +1,49 @@
|
||||
SUBDIRS = ctrl util platform
|
||||
|
||||
aggincludedir = $(includedir)/agg2
|
||||
agginclude_HEADERS = \
|
||||
agg_alpha_mask_u8.h agg_glyph_raster_bin.h agg_span_allocator.h \
|
||||
agg_arc.h agg_gsv_text.h agg_span_converter.h \
|
||||
agg_array.h agg_image_accessors.h agg_span_gouraud.h \
|
||||
agg_arrowhead.h agg_image_filters.h agg_span_gouraud_gray.h \
|
||||
agg_basics.h agg_line_aa_basics.h agg_span_gouraud_rgba.h \
|
||||
agg_bezier_arc.h agg_math.h agg_span_gradient.h \
|
||||
agg_bitset_iterator.h agg_blur.h agg_math_stroke.h \
|
||||
agg_span_gradient_alpha.h agg_gradient_lut.h \
|
||||
agg_bounding_rect.h agg_path_length.h agg_span_image_filter.h \
|
||||
agg_bspline.h agg_path_storage.h agg_span_image_filter_gray.h \
|
||||
agg_clip_liang_barsky.h agg_path_storage_integer.h agg_span_image_filter_rgb.h \
|
||||
agg_color_gray.h agg_pattern_filters_rgba.h agg_span_image_filter_rgba.h \
|
||||
agg_color_rgba.h agg_pixfmt_amask_adaptor.h agg_span_interpolator_adaptor.h \
|
||||
agg_config.h agg_pixfmt_gray.h agg_span_interpolator_linear.h \
|
||||
agg_conv_adaptor_vcgen.h agg_pixfmt_rgb.h agg_span_interpolator_persp.h \
|
||||
agg_conv_adaptor_vpgen.h agg_pixfmt_rgb_packed.h agg_span_interpolator_trans.h \
|
||||
agg_conv_bspline.h agg_pixfmt_rgba.h agg_pixfmt_transposer.h \
|
||||
agg_span_pattern_gray.h \
|
||||
agg_conv_clip_polygon.h agg_rasterizer_cells_aa.h agg_span_pattern_rgb.h \
|
||||
agg_conv_clip_polyline.h agg_rasterizer_compound_aa.h agg_span_pattern_rgba.h \
|
||||
agg_conv_close_polygon.h agg_rasterizer_outline.h agg_span_solid.h \
|
||||
agg_conv_concat.h agg_rasterizer_outline_aa.h agg_span_subdiv_adaptor.h \
|
||||
agg_conv_contour.h agg_rasterizer_scanline_aa.h agg_trans_affine.h \
|
||||
agg_conv_curve.h agg_rasterizer_sl_clip.h agg_trans_bilinear.h \
|
||||
agg_conv_dash.h agg_renderer_base.h agg_trans_double_path.h \
|
||||
agg_conv_gpc.h agg_renderer_markers.h \
|
||||
agg_conv_marker.h agg_renderer_mclip.h agg_trans_perspective.h \
|
||||
agg_conv_marker_adaptor.h agg_renderer_outline_aa.h agg_trans_single_path.h \
|
||||
agg_conv_segmentator.h agg_renderer_outline_image.h agg_trans_viewport.h \
|
||||
agg_conv_shorten_path.h agg_renderer_primitives.h agg_trans_warp_magnifier.h \
|
||||
agg_conv_smooth_poly1.h agg_renderer_raster_text.h agg_vcgen_bspline.h \
|
||||
agg_conv_stroke.h agg_renderer_scanline.h agg_vcgen_contour.h \
|
||||
agg_conv_transform.h agg_rendering_buffer.h agg_vcgen_dash.h \
|
||||
agg_conv_unclose_polygon.h agg_rendering_buffer_dynarow.h agg_vcgen_markers_term.h \
|
||||
agg_curves.h agg_rounded_rect.h agg_vcgen_smooth_poly1.h \
|
||||
agg_scanline_bin.h agg_vcgen_stroke.h \
|
||||
agg_dda_line.h agg_scanline_boolean_algebra.h agg_vcgen_vertex_sequence.h \
|
||||
agg_ellipse.h agg_scanline_p.h agg_vertex_sequence.h \
|
||||
agg_ellipse_bresenham.h agg_scanline_storage_aa.h agg_vpgen_clip_polygon.h \
|
||||
agg_embedded_raster_fonts.h agg_scanline_storage_bin.h agg_vpgen_clip_polyline.h \
|
||||
agg_font_cache_manager.h agg_scanline_u.h agg_vpgen_segmentator.h \
|
||||
agg_gamma_functions.h agg_shorten_path.h \
|
||||
agg_gamma_lut.h agg_simul_eq.h \
|
||||
agg_font_cache_manager2.h agg_pixfmt_base.h agg_rasterizer_scanline_aa_nogamma.h \
|
||||
agg_span_gradient_contour.h agg_span_gradient_image.h
|
||||
568
dep/agg/include/agg2d.h
Normal file
568
dep/agg/include/agg2d.h
Normal file
@@ -0,0 +1,568 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// Agg2D - Version 1.0
|
||||
// Based on Anti-Grain Geometry
|
||||
// Copyright (C) 2005 Maxim Shemanarev (http://www.antigrain.com)
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all copies.
|
||||
// This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// 25 Jan 2007 - Ported to AGG 2.4 Jerry Evans (jerry@novadsp.com)
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG2D_INCLUDED
|
||||
#define AGG2D_INCLUDED
|
||||
|
||||
// With this define uncommented you can use floating-point pixel format
|
||||
//#define AGG2D_USE_FLOAT_FORMAT
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_trans_affine.h"
|
||||
#include "agg_trans_viewport.h"
|
||||
#include "agg_path_storage.h"
|
||||
#include "agg_conv_stroke.h"
|
||||
#include "agg_conv_transform.h"
|
||||
#include "agg_conv_curve.h"
|
||||
#include "agg_rendering_buffer.h"
|
||||
#include "agg_renderer_base.h"
|
||||
#include "agg_renderer_scanline.h"
|
||||
#include "agg_span_gradient.h"
|
||||
#include "agg_span_image_filter_rgba.h"
|
||||
#include "agg_span_allocator.h"
|
||||
#include "agg_span_converter.h"
|
||||
#include "agg_span_interpolator_linear.h"
|
||||
#include "agg_rasterizer_scanline_aa.h"
|
||||
#include "agg_gamma_functions.h"
|
||||
#include "agg_scanline_u.h"
|
||||
#include "agg_bezier_arc.h"
|
||||
#include "agg_rounded_rect.h"
|
||||
#include "agg_font_cache_manager.h"
|
||||
|
||||
#include "agg_pixfmt_rgba.h"
|
||||
#include "agg_image_accessors.h"
|
||||
#include <string>
|
||||
|
||||
class Agg2D
|
||||
{
|
||||
#ifdef AGG2D_USE_FLOAT_FORMAT
|
||||
typedef agg::rgba32 ColorType;
|
||||
#else
|
||||
typedef agg::rgba8 ColorType;
|
||||
#endif
|
||||
typedef agg::order_bgra ComponentOrder; // Platform dependent!
|
||||
typedef agg::blender_rgba<ColorType, ComponentOrder> Blender;
|
||||
typedef agg::comp_op_adaptor_rgba<ColorType, ComponentOrder> BlenderComp;
|
||||
typedef agg::blender_rgba_pre<ColorType, ComponentOrder> BlenderPre;
|
||||
typedef agg::comp_op_adaptor_rgba_pre<ColorType, ComponentOrder> BlenderCompPre;
|
||||
|
||||
typedef agg::pixfmt_alpha_blend_rgba<Blender, agg::rendering_buffer> PixFormat;
|
||||
typedef agg::pixfmt_custom_blend_rgba<BlenderComp, agg::rendering_buffer> PixFormatComp;
|
||||
typedef agg::pixfmt_alpha_blend_rgba<BlenderPre, agg::rendering_buffer> PixFormatPre;
|
||||
typedef agg::pixfmt_custom_blend_rgba<BlenderCompPre, agg::rendering_buffer> PixFormatCompPre;
|
||||
|
||||
typedef agg::renderer_base<PixFormat> RendererBase;
|
||||
typedef agg::renderer_base<PixFormatComp> RendererBaseComp;
|
||||
typedef agg::renderer_base<PixFormatPre> RendererBasePre;
|
||||
typedef agg::renderer_base<PixFormatCompPre> RendererBaseCompPre;
|
||||
|
||||
typedef agg::renderer_scanline_aa_solid<RendererBase> RendererSolid;
|
||||
typedef agg::renderer_scanline_aa_solid<RendererBaseComp> RendererSolidComp;
|
||||
|
||||
typedef agg::span_allocator<ColorType> SpanAllocator;
|
||||
typedef agg::pod_auto_array<ColorType, 256> GradientArray;
|
||||
|
||||
typedef agg::span_gradient<ColorType, agg::span_interpolator_linear<>, agg::gradient_x, GradientArray> LinearGradientSpan;
|
||||
typedef agg::span_gradient<ColorType, agg::span_interpolator_linear<>, agg::gradient_circle, GradientArray> RadialGradientSpan;
|
||||
|
||||
typedef agg::conv_curve<agg::path_storage> ConvCurve;
|
||||
typedef agg::conv_stroke<ConvCurve> ConvStroke;
|
||||
typedef agg::conv_transform<ConvCurve> PathTransform;
|
||||
typedef agg::conv_transform<ConvStroke> StrokeTransform;
|
||||
|
||||
enum Gradient
|
||||
{
|
||||
Solid,
|
||||
Linear,
|
||||
Radial
|
||||
};
|
||||
|
||||
public:
|
||||
friend class Agg2DRenderer;
|
||||
|
||||
// Use srgba8 as the "user" color type, even though the underlying color type
|
||||
// might be something else, such as rgba32. This allows code based on
|
||||
// 8-bit sRGB values to carry on working as before.
|
||||
typedef agg::srgba8 Color;
|
||||
typedef agg::rect_i Rect;
|
||||
typedef agg::rect_d RectD;
|
||||
typedef agg::trans_affine Affine;
|
||||
|
||||
enum LineJoin
|
||||
{
|
||||
JoinMiter = agg::miter_join,
|
||||
JoinRound = agg::round_join,
|
||||
JoinBevel = agg::bevel_join
|
||||
};
|
||||
|
||||
enum LineCap
|
||||
{
|
||||
CapButt = agg::butt_cap,
|
||||
CapSquare = agg::square_cap,
|
||||
CapRound = agg::round_cap
|
||||
};
|
||||
|
||||
enum TextAlignment
|
||||
{
|
||||
AlignLeft,
|
||||
AlignRight,
|
||||
AlignCenter,
|
||||
};
|
||||
|
||||
|
||||
enum DrawPathFlag
|
||||
{
|
||||
FillOnly,
|
||||
StrokeOnly,
|
||||
FillAndStroke,
|
||||
FillWithLineColor
|
||||
};
|
||||
|
||||
enum ViewportOption
|
||||
{
|
||||
Anisotropic,
|
||||
XMinYMin,
|
||||
XMidYMin,
|
||||
XMaxYMin,
|
||||
XMinYMid,
|
||||
XMidYMid,
|
||||
XMaxYMid,
|
||||
XMinYMax,
|
||||
XMidYMax,
|
||||
XMaxYMax
|
||||
};
|
||||
|
||||
struct Transformations
|
||||
{
|
||||
double affineMatrix[6];
|
||||
};
|
||||
|
||||
|
||||
struct Image
|
||||
{
|
||||
agg::rendering_buffer renBuf;
|
||||
|
||||
Image() {}
|
||||
Image(unsigned char* buf, unsigned width, unsigned height, int stride) :
|
||||
renBuf(buf, width, height, stride) {}
|
||||
void attach(unsigned char* buf, unsigned width, unsigned height, int stride)
|
||||
{
|
||||
renBuf.attach(buf, width, height, stride);
|
||||
}
|
||||
int width() const { return renBuf.width(); }
|
||||
int height() const { return renBuf.height(); }
|
||||
void premultiply();
|
||||
void demultiply();
|
||||
};
|
||||
|
||||
enum ImageFilter
|
||||
{
|
||||
NoFilter,
|
||||
Bilinear,
|
||||
Hanning,
|
||||
Hermite,
|
||||
Quadric,
|
||||
Bicubic,
|
||||
Catrom,
|
||||
Spline16,
|
||||
Spline36,
|
||||
Blackman144
|
||||
};
|
||||
|
||||
enum ImageResample
|
||||
{
|
||||
NoResample,
|
||||
ResampleAlways,
|
||||
ResampleOnZoomOut
|
||||
};
|
||||
|
||||
enum FontCacheType
|
||||
{
|
||||
RasterFontCache,
|
||||
VectorFontCache
|
||||
};
|
||||
|
||||
enum BlendMode
|
||||
{
|
||||
BlendAlpha = agg::end_of_comp_op_e,
|
||||
BlendClear = agg::comp_op_clear,
|
||||
BlendSrc = agg::comp_op_src,
|
||||
BlendDst = agg::comp_op_dst,
|
||||
BlendSrcOver = agg::comp_op_src_over,
|
||||
BlendDstOver = agg::comp_op_dst_over,
|
||||
BlendSrcIn = agg::comp_op_src_in,
|
||||
BlendDstIn = agg::comp_op_dst_in,
|
||||
BlendSrcOut = agg::comp_op_src_out,
|
||||
BlendDstOut = agg::comp_op_dst_out,
|
||||
BlendSrcAtop = agg::comp_op_src_atop,
|
||||
BlendDstAtop = agg::comp_op_dst_atop,
|
||||
BlendXor = agg::comp_op_xor,
|
||||
BlendAdd = agg::comp_op_plus,
|
||||
BlendMultiply = agg::comp_op_multiply,
|
||||
BlendScreen = agg::comp_op_screen,
|
||||
BlendOverlay = agg::comp_op_overlay,
|
||||
BlendDarken = agg::comp_op_darken,
|
||||
BlendLighten = agg::comp_op_lighten,
|
||||
BlendColorDodge = agg::comp_op_color_dodge,
|
||||
BlendColorBurn = agg::comp_op_color_burn,
|
||||
BlendHardLight = agg::comp_op_hard_light,
|
||||
BlendSoftLight = agg::comp_op_soft_light,
|
||||
BlendDifference = agg::comp_op_difference,
|
||||
BlendExclusion = agg::comp_op_exclusion,
|
||||
};
|
||||
|
||||
enum Direction
|
||||
{
|
||||
CW, CCW
|
||||
};
|
||||
|
||||
~Agg2D();
|
||||
Agg2D();
|
||||
|
||||
// Setup
|
||||
//-----------------------
|
||||
void attach(unsigned char* buf, unsigned width, unsigned height, int stride);
|
||||
void attach(Image& img);
|
||||
|
||||
void clipBox(double x1, double y1, double x2, double y2);
|
||||
RectD clipBox() const;
|
||||
|
||||
void clearAll(Color c);
|
||||
void clearAll(unsigned r, unsigned g, unsigned b, unsigned a = 255);
|
||||
|
||||
void clearClipBox(Color c);
|
||||
void clearClipBox(unsigned r, unsigned g, unsigned b, unsigned a = 255);
|
||||
|
||||
// Conversions
|
||||
//-----------------------
|
||||
void worldToScreen(double& x, double& y) const;
|
||||
void screenToWorld(double& x, double& y) const;
|
||||
double worldToScreen(double scalar) const;
|
||||
double screenToWorld(double scalar) const;
|
||||
void alignPoint(double& x, double& y) const;
|
||||
bool inBox(double worldX, double worldY) const;
|
||||
|
||||
// General Attributes
|
||||
//-----------------------
|
||||
void blendMode(BlendMode m);
|
||||
BlendMode blendMode() const;
|
||||
|
||||
void imageBlendMode(BlendMode m);
|
||||
BlendMode imageBlendMode() const;
|
||||
|
||||
void imageBlendColor(Color c);
|
||||
void imageBlendColor(unsigned r, unsigned g, unsigned b, unsigned a = 255);
|
||||
Color imageBlendColor() const;
|
||||
|
||||
void masterAlpha(double a);
|
||||
double masterAlpha() const;
|
||||
|
||||
void antiAliasGamma(double g);
|
||||
double antiAliasGamma() const;
|
||||
|
||||
void fillColor(Color c);
|
||||
void fillColor(unsigned r, unsigned g, unsigned b, unsigned a = 255);
|
||||
void noFill();
|
||||
|
||||
void lineColor(Color c);
|
||||
void lineColor(unsigned r, unsigned g, unsigned b, unsigned a = 255);
|
||||
void noLine();
|
||||
|
||||
Color fillColor() const;
|
||||
Color lineColor() const;
|
||||
|
||||
void fillLinearGradient(double x1, double y1, double x2, double y2, Color c1, Color c2, double profile=1.0);
|
||||
void lineLinearGradient(double x1, double y1, double x2, double y2, Color c1, Color c2, double profile=1.0);
|
||||
|
||||
void fillRadialGradient(double x, double y, double r, Color c1, Color c2, double profile=1.0);
|
||||
void lineRadialGradient(double x, double y, double r, Color c1, Color c2, double profile=1.0);
|
||||
|
||||
void fillRadialGradient(double x, double y, double r, Color c1, Color c2, Color c3);
|
||||
void lineRadialGradient(double x, double y, double r, Color c1, Color c2, Color c3);
|
||||
|
||||
void fillRadialGradient(double x, double y, double r);
|
||||
void lineRadialGradient(double x, double y, double r);
|
||||
|
||||
void lineWidth(double w);
|
||||
double lineWidth(double w) const;
|
||||
|
||||
void lineCap(LineCap cap);
|
||||
LineCap lineCap() const;
|
||||
|
||||
void lineJoin(LineJoin join);
|
||||
LineJoin lineJoin() const;
|
||||
|
||||
void fillEvenOdd(bool evenOddFlag);
|
||||
bool fillEvenOdd() const;
|
||||
|
||||
void textAlignment(TextAlignment alignment);
|
||||
void textSize(double sizeX, double sizeY);
|
||||
inline void textSize(double size) { textSize(size, size); }
|
||||
|
||||
// Transformations
|
||||
//-----------------------
|
||||
Transformations transformations() const;
|
||||
void transformations(const Transformations& tr);
|
||||
void resetTransformations();
|
||||
void affine(const Affine& tr);
|
||||
void affine(const Transformations& tr);
|
||||
void rotate(double angle);
|
||||
void scale(double sx, double sy);
|
||||
void skew(double sx, double sy);
|
||||
void translate(double x, double y);
|
||||
void parallelogram(double x1, double y1, double x2, double y2, const double* para);
|
||||
void viewport(double worldX1, double worldY1, double worldX2, double worldY2,
|
||||
double screenX1, double screenY1, double screenX2, double screenY2,
|
||||
ViewportOption opt=XMidYMid);
|
||||
|
||||
// Basic Shapes
|
||||
//-----------------------
|
||||
void line(double x1, double y1, double x2, double y2);
|
||||
void triangle(double x1, double y1, double x2, double y2, double x3, double y3);
|
||||
void rectangle(double x1, double y1, double x2, double y2);
|
||||
void roundedRect(double x1, double y1, double x2, double y2, double r);
|
||||
void roundedRect(double x1, double y1, double x2, double y2, double rx, double ry);
|
||||
void roundedRect(double x1, double y1, double x2, double y2,
|
||||
double rxBottom, double ryBottom,
|
||||
double rxTop, double ryTop);
|
||||
void ellipse(double cx, double cy, double rx, double ry);
|
||||
void arc(double cx, double cy, double rx, double ry, double start, double sweep);
|
||||
void star(double cx, double cy, double r1, double r2, double startAngle, int numRays);
|
||||
void curve(double x1, double y1, double x2, double y2, double x3, double y3);
|
||||
void curve(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4);
|
||||
void polygon(double* xy, int numPoints);
|
||||
void polyline(double* xy, int numPoints);
|
||||
|
||||
// Path commands
|
||||
//-----------------------
|
||||
void resetPath();
|
||||
|
||||
void moveTo(double x, double y);
|
||||
void moveRel(double dx, double dy);
|
||||
|
||||
void lineTo(double x, double y);
|
||||
void lineRel(double dx, double dy);
|
||||
|
||||
void horLineTo(double x);
|
||||
void horLineRel(double dx);
|
||||
|
||||
void verLineTo(double y);
|
||||
void verLineRel(double dy);
|
||||
|
||||
void arcTo(double rx, double ry,
|
||||
double angle,
|
||||
bool largeArcFlag,
|
||||
bool sweepFlag,
|
||||
double x, double y);
|
||||
|
||||
void arcRel(double rx, double ry,
|
||||
double angle,
|
||||
bool largeArcFlag,
|
||||
bool sweepFlag,
|
||||
double dx, double dy);
|
||||
|
||||
void quadricCurveTo(double xCtrl, double yCtrl,
|
||||
double xTo, double yTo);
|
||||
void quadricCurveRel(double dxCtrl, double dyCtrl,
|
||||
double dxTo, double dyTo);
|
||||
void quadricCurveTo(double xTo, double yTo);
|
||||
void quadricCurveRel(double dxTo, double dyTo);
|
||||
|
||||
void cubicCurveTo(double xCtrl1, double yCtrl1,
|
||||
double xCtrl2, double yCtrl2,
|
||||
double xTo, double yTo);
|
||||
|
||||
void cubicCurveRel(double dxCtrl1, double dyCtrl1,
|
||||
double dxCtrl2, double dyCtrl2,
|
||||
double dxTo, double dyTo);
|
||||
|
||||
void cubicCurveTo(double xCtrl2, double yCtrl2,
|
||||
double xTo, double yTo);
|
||||
|
||||
void cubicCurveRel(double xCtrl2, double yCtrl2,
|
||||
double xTo, double yTo);
|
||||
|
||||
void addEllipse(double cx, double cy, double rx, double ry, Direction dir);
|
||||
void text(double x, double y, const std::string& text);
|
||||
void closePolygon();
|
||||
|
||||
void drawPath(DrawPathFlag flag = FillAndStroke);
|
||||
void drawPathNoTransform(DrawPathFlag flag = FillAndStroke);
|
||||
|
||||
|
||||
// Image Transformations
|
||||
//-----------------------
|
||||
void imageFilter(ImageFilter f);
|
||||
ImageFilter imageFilter() const;
|
||||
|
||||
void imageResample(ImageResample f);
|
||||
ImageResample imageResample() const;
|
||||
|
||||
void transformImage(const Image& img,
|
||||
int imgX1, int imgY1, int imgX2, int imgY2,
|
||||
double dstX1, double dstY1, double dstX2, double dstY2);
|
||||
|
||||
void transformImage(const Image& img,
|
||||
double dstX1, double dstY1, double dstX2, double dstY2);
|
||||
|
||||
void transformImage(const Image& img,
|
||||
int imgX1, int imgY1, int imgX2, int imgY2,
|
||||
const double* parallelogram);
|
||||
|
||||
void transformImage(const Image& img, const double* parallelogram);
|
||||
|
||||
|
||||
void transformImagePath(const Image& img,
|
||||
int imgX1, int imgY1, int imgX2, int imgY2,
|
||||
double dstX1, double dstY1, double dstX2, double dstY2);
|
||||
|
||||
void transformImagePath(const Image& img,
|
||||
double dstX1, double dstY1, double dstX2, double dstY2);
|
||||
|
||||
void transformImagePath(const Image& img,
|
||||
int imgX1, int imgY1, int imgX2, int imgY2,
|
||||
const double* parallelogram);
|
||||
|
||||
void transformImagePath(const Image& img, const double* parallelogram);
|
||||
|
||||
|
||||
// Image Blending (no transformations available)
|
||||
void blendImage(Image& img,
|
||||
int imgX1, int imgY1, int imgX2, int imgY2,
|
||||
double dstX, double dstY, unsigned alpha=255);
|
||||
void blendImage(Image& img, double dstX, double dstY, unsigned alpha=255);
|
||||
|
||||
|
||||
// Copy image directly, together with alpha-channel
|
||||
void copyImage(Image& img,
|
||||
int imgX1, int imgY1, int imgX2, int imgY2,
|
||||
double dstX, double dstY);
|
||||
void copyImage(Image& img, double dstX, double dstY);
|
||||
|
||||
|
||||
// Auxiliary
|
||||
//-----------------------
|
||||
static double pi() { return agg::pi; }
|
||||
static double deg2Rad(double v) { return v * agg::pi / 180.0; }
|
||||
static double rad2Deg(double v) { return v * 180.0 / agg::pi; }
|
||||
|
||||
private:
|
||||
void render(bool fillColor);
|
||||
#ifdef AGG_USE_FONTS
|
||||
void render(FontRasterizer& ras, FontScanline& sl);
|
||||
#endif // AGG_USE_FONTS
|
||||
|
||||
void addLine(double x1, double y1, double x2, double y2);
|
||||
void updateRasterizerGamma();
|
||||
void renderImage(const Image& img, int x1, int y1, int x2, int y2, const double* parl);
|
||||
|
||||
agg::rendering_buffer m_rbuf;
|
||||
PixFormat m_pixFormat;
|
||||
PixFormatComp m_pixFormatComp;
|
||||
PixFormatPre m_pixFormatPre;
|
||||
PixFormatCompPre m_pixFormatCompPre;
|
||||
RendererBase m_renBase;
|
||||
RendererBaseComp m_renBaseComp;
|
||||
RendererBasePre m_renBasePre;
|
||||
RendererBaseCompPre m_renBaseCompPre;
|
||||
RendererSolid m_renSolid;
|
||||
RendererSolidComp m_renSolidComp;
|
||||
|
||||
SpanAllocator m_allocator;
|
||||
RectD m_clipBox;
|
||||
|
||||
BlendMode m_blendMode;
|
||||
BlendMode m_imageBlendMode;
|
||||
Color m_imageBlendColor;
|
||||
|
||||
agg::scanline_u8 m_scanline;
|
||||
agg::rasterizer_scanline_aa<> m_rasterizer;
|
||||
|
||||
double m_masterAlpha;
|
||||
double m_antiAliasGamma;
|
||||
|
||||
Color m_fillColor;
|
||||
Color m_lineColor;
|
||||
GradientArray m_fillGradient;
|
||||
GradientArray m_lineGradient;
|
||||
|
||||
LineCap m_lineCap;
|
||||
LineJoin m_lineJoin;
|
||||
|
||||
Gradient m_fillGradientFlag;
|
||||
Gradient m_lineGradientFlag;
|
||||
agg::trans_affine m_fillGradientMatrix;
|
||||
agg::trans_affine m_lineGradientMatrix;
|
||||
double m_fillGradientD1;
|
||||
double m_lineGradientD1;
|
||||
double m_fillGradientD2;
|
||||
double m_lineGradientD2;
|
||||
|
||||
TextAlignment m_textAlignment;
|
||||
double m_textSizeX;
|
||||
double m_textSizeY;
|
||||
|
||||
ImageFilter m_imageFilter;
|
||||
ImageResample m_imageResample;
|
||||
agg::image_filter_lut m_imageFilterLut;
|
||||
|
||||
agg::span_interpolator_linear<> m_fillGradientInterpolator;
|
||||
agg::span_interpolator_linear<> m_lineGradientInterpolator;
|
||||
|
||||
agg::gradient_x m_linearGradientFunction;
|
||||
agg::gradient_circle m_radialGradientFunction;
|
||||
|
||||
double m_lineWidth;
|
||||
bool m_evenOddFlag;
|
||||
|
||||
agg::path_storage m_path;
|
||||
agg::trans_affine m_transform;
|
||||
|
||||
ConvCurve m_convCurve;
|
||||
ConvStroke m_convStroke;
|
||||
|
||||
PathTransform m_pathTransform;
|
||||
StrokeTransform m_strokeTransform;
|
||||
|
||||
#ifdef AGG_USE_FONTS
|
||||
#ifndef AGG2D_USE_FREETYPE
|
||||
HDC m_fontDC;
|
||||
#endif
|
||||
FontEngine m_fontEngine;
|
||||
FontCacheManager m_fontCacheManager;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
inline bool operator == (const Agg2D::Color& c1, const Agg2D::Color& c2)
|
||||
{
|
||||
return c1.r == c2.r && c1.g == c2.g && c1.b == c2.b && c1.a == c2.a;
|
||||
}
|
||||
|
||||
inline bool operator != (const Agg2D::Color& c1, const Agg2D::Color& c2)
|
||||
{
|
||||
return !(c1 == c2);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
499
dep/agg/include/agg_alpha_mask_u8.h
Normal file
499
dep/agg/include/agg_alpha_mask_u8.h
Normal file
@@ -0,0 +1,499 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.4
|
||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all copies.
|
||||
// This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// scanline_u8 class
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
#ifndef AGG_ALPHA_MASK_U8_INCLUDED
|
||||
#define AGG_ALPHA_MASK_U8_INCLUDED
|
||||
|
||||
#include <cstring>
|
||||
#include "agg_basics.h"
|
||||
#include "agg_rendering_buffer.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//===================================================one_component_mask_u8
|
||||
struct one_component_mask_u8
|
||||
{
|
||||
static unsigned calculate(const int8u* p) { return *p; }
|
||||
};
|
||||
|
||||
|
||||
//=====================================================rgb_to_gray_mask_u8
|
||||
template<unsigned R, unsigned G, unsigned B>
|
||||
struct rgb_to_gray_mask_u8
|
||||
{
|
||||
static unsigned calculate(const int8u* p)
|
||||
{
|
||||
return (p[R]*77 + p[G]*150 + p[B]*29) >> 8;
|
||||
}
|
||||
};
|
||||
|
||||
//==========================================================alpha_mask_u8
|
||||
template<unsigned Step=1, unsigned Offset=0, class MaskF=one_component_mask_u8>
|
||||
class alpha_mask_u8
|
||||
{
|
||||
public:
|
||||
typedef int8u cover_type;
|
||||
typedef alpha_mask_u8<Step, Offset, MaskF> self_type;
|
||||
enum cover_scale_e
|
||||
{
|
||||
cover_shift = 8,
|
||||
cover_none = 0,
|
||||
cover_full = 255
|
||||
};
|
||||
|
||||
alpha_mask_u8() : m_rbuf(0) {}
|
||||
explicit alpha_mask_u8(rendering_buffer& rbuf) : m_rbuf(&rbuf) {}
|
||||
|
||||
void attach(rendering_buffer& rbuf) { m_rbuf = &rbuf; }
|
||||
|
||||
MaskF& mask_function() { return m_mask_function; }
|
||||
const MaskF& mask_function() const { return m_mask_function; }
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
cover_type pixel(int x, int y) const
|
||||
{
|
||||
if(x >= 0 && y >= 0 &&
|
||||
x < (int)m_rbuf->width() &&
|
||||
y < (int)m_rbuf->height())
|
||||
{
|
||||
return (cover_type)m_mask_function.calculate(
|
||||
m_rbuf->row_ptr(y) + x * Step + Offset);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
cover_type combine_pixel(int x, int y, cover_type val) const
|
||||
{
|
||||
if(x >= 0 && y >= 0 &&
|
||||
x < (int)m_rbuf->width() &&
|
||||
y < (int)m_rbuf->height())
|
||||
{
|
||||
return (cover_type)((cover_full + val *
|
||||
m_mask_function.calculate(
|
||||
m_rbuf->row_ptr(y) + x * Step + Offset)) >>
|
||||
cover_shift);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void fill_hspan(int x, int y, cover_type* dst, int num_pix) const
|
||||
{
|
||||
int xmax = m_rbuf->width() - 1;
|
||||
int ymax = m_rbuf->height() - 1;
|
||||
|
||||
int count = num_pix;
|
||||
cover_type* covers = dst;
|
||||
|
||||
if(y < 0 || y > ymax)
|
||||
{
|
||||
std::memset(dst, 0, num_pix * sizeof(cover_type));
|
||||
return;
|
||||
}
|
||||
|
||||
if(x < 0)
|
||||
{
|
||||
count += x;
|
||||
if(count <= 0)
|
||||
{
|
||||
std::memset(dst, 0, num_pix * sizeof(cover_type));
|
||||
return;
|
||||
}
|
||||
std::memset(covers, 0, -x * sizeof(cover_type));
|
||||
covers -= x;
|
||||
x = 0;
|
||||
}
|
||||
|
||||
if(x + count > xmax)
|
||||
{
|
||||
int rest = x + count - xmax - 1;
|
||||
count -= rest;
|
||||
if(count <= 0)
|
||||
{
|
||||
std::memset(dst, 0, num_pix * sizeof(cover_type));
|
||||
return;
|
||||
}
|
||||
std::memset(covers + count, 0, rest * sizeof(cover_type));
|
||||
}
|
||||
|
||||
const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
|
||||
do
|
||||
{
|
||||
*covers++ = (cover_type)m_mask_function.calculate(mask);
|
||||
mask += Step;
|
||||
}
|
||||
while(--count);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void combine_hspan(int x, int y, cover_type* dst, int num_pix) const
|
||||
{
|
||||
int xmax = m_rbuf->width() - 1;
|
||||
int ymax = m_rbuf->height() - 1;
|
||||
|
||||
int count = num_pix;
|
||||
cover_type* covers = dst;
|
||||
|
||||
if(y < 0 || y > ymax)
|
||||
{
|
||||
std::memset(dst, 0, num_pix * sizeof(cover_type));
|
||||
return;
|
||||
}
|
||||
|
||||
if(x < 0)
|
||||
{
|
||||
count += x;
|
||||
if(count <= 0)
|
||||
{
|
||||
std::memset(dst, 0, num_pix * sizeof(cover_type));
|
||||
return;
|
||||
}
|
||||
std::memset(covers, 0, -x * sizeof(cover_type));
|
||||
covers -= x;
|
||||
x = 0;
|
||||
}
|
||||
|
||||
if(x + count > xmax)
|
||||
{
|
||||
int rest = x + count - xmax - 1;
|
||||
count -= rest;
|
||||
if(count <= 0)
|
||||
{
|
||||
std::memset(dst, 0, num_pix * sizeof(cover_type));
|
||||
return;
|
||||
}
|
||||
std::memset(covers + count, 0, rest * sizeof(cover_type));
|
||||
}
|
||||
|
||||
const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
|
||||
do
|
||||
{
|
||||
*covers = (cover_type)((cover_full + (*covers) *
|
||||
m_mask_function.calculate(mask)) >>
|
||||
cover_shift);
|
||||
++covers;
|
||||
mask += Step;
|
||||
}
|
||||
while(--count);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void fill_vspan(int x, int y, cover_type* dst, int num_pix) const
|
||||
{
|
||||
int xmax = m_rbuf->width() - 1;
|
||||
int ymax = m_rbuf->height() - 1;
|
||||
|
||||
int count = num_pix;
|
||||
cover_type* covers = dst;
|
||||
|
||||
if(x < 0 || x > xmax)
|
||||
{
|
||||
std::memset(dst, 0, num_pix * sizeof(cover_type));
|
||||
return;
|
||||
}
|
||||
|
||||
if(y < 0)
|
||||
{
|
||||
count += y;
|
||||
if(count <= 0)
|
||||
{
|
||||
std::memset(dst, 0, num_pix * sizeof(cover_type));
|
||||
return;
|
||||
}
|
||||
std::memset(covers, 0, -y * sizeof(cover_type));
|
||||
covers -= y;
|
||||
y = 0;
|
||||
}
|
||||
|
||||
if(y + count > ymax)
|
||||
{
|
||||
int rest = y + count - ymax - 1;
|
||||
count -= rest;
|
||||
if(count <= 0)
|
||||
{
|
||||
std::memset(dst, 0, num_pix * sizeof(cover_type));
|
||||
return;
|
||||
}
|
||||
std::memset(covers + count, 0, rest * sizeof(cover_type));
|
||||
}
|
||||
|
||||
const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
|
||||
do
|
||||
{
|
||||
*covers++ = (cover_type)m_mask_function.calculate(mask);
|
||||
mask += m_rbuf->stride();
|
||||
}
|
||||
while(--count);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void combine_vspan(int x, int y, cover_type* dst, int num_pix) const
|
||||
{
|
||||
int xmax = m_rbuf->width() - 1;
|
||||
int ymax = m_rbuf->height() - 1;
|
||||
|
||||
int count = num_pix;
|
||||
cover_type* covers = dst;
|
||||
|
||||
if(x < 0 || x > xmax)
|
||||
{
|
||||
std::memset(dst, 0, num_pix * sizeof(cover_type));
|
||||
return;
|
||||
}
|
||||
|
||||
if(y < 0)
|
||||
{
|
||||
count += y;
|
||||
if(count <= 0)
|
||||
{
|
||||
std::memset(dst, 0, num_pix * sizeof(cover_type));
|
||||
return;
|
||||
}
|
||||
std::memset(covers, 0, -y * sizeof(cover_type));
|
||||
covers -= y;
|
||||
y = 0;
|
||||
}
|
||||
|
||||
if(y + count > ymax)
|
||||
{
|
||||
int rest = y + count - ymax - 1;
|
||||
count -= rest;
|
||||
if(count <= 0)
|
||||
{
|
||||
std::memset(dst, 0, num_pix * sizeof(cover_type));
|
||||
return;
|
||||
}
|
||||
std::memset(covers + count, 0, rest * sizeof(cover_type));
|
||||
}
|
||||
|
||||
const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
|
||||
do
|
||||
{
|
||||
*covers = (cover_type)((cover_full + (*covers) *
|
||||
m_mask_function.calculate(mask)) >>
|
||||
cover_shift);
|
||||
++covers;
|
||||
mask += m_rbuf->stride();
|
||||
}
|
||||
while(--count);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
alpha_mask_u8(const self_type&);
|
||||
const self_type& operator = (const self_type&);
|
||||
|
||||
rendering_buffer* m_rbuf;
|
||||
MaskF m_mask_function;
|
||||
};
|
||||
|
||||
|
||||
typedef alpha_mask_u8<1, 0> alpha_mask_gray8; //----alpha_mask_gray8
|
||||
|
||||
typedef alpha_mask_u8<3, 0> alpha_mask_rgb24r; //----alpha_mask_rgb24r
|
||||
typedef alpha_mask_u8<3, 1> alpha_mask_rgb24g; //----alpha_mask_rgb24g
|
||||
typedef alpha_mask_u8<3, 2> alpha_mask_rgb24b; //----alpha_mask_rgb24b
|
||||
|
||||
typedef alpha_mask_u8<3, 2> alpha_mask_bgr24r; //----alpha_mask_bgr24r
|
||||
typedef alpha_mask_u8<3, 1> alpha_mask_bgr24g; //----alpha_mask_bgr24g
|
||||
typedef alpha_mask_u8<3, 0> alpha_mask_bgr24b; //----alpha_mask_bgr24b
|
||||
|
||||
typedef alpha_mask_u8<4, 0> alpha_mask_rgba32r; //----alpha_mask_rgba32r
|
||||
typedef alpha_mask_u8<4, 1> alpha_mask_rgba32g; //----alpha_mask_rgba32g
|
||||
typedef alpha_mask_u8<4, 2> alpha_mask_rgba32b; //----alpha_mask_rgba32b
|
||||
typedef alpha_mask_u8<4, 3> alpha_mask_rgba32a; //----alpha_mask_rgba32a
|
||||
|
||||
typedef alpha_mask_u8<4, 1> alpha_mask_argb32r; //----alpha_mask_argb32r
|
||||
typedef alpha_mask_u8<4, 2> alpha_mask_argb32g; //----alpha_mask_argb32g
|
||||
typedef alpha_mask_u8<4, 3> alpha_mask_argb32b; //----alpha_mask_argb32b
|
||||
typedef alpha_mask_u8<4, 0> alpha_mask_argb32a; //----alpha_mask_argb32a
|
||||
|
||||
typedef alpha_mask_u8<4, 2> alpha_mask_bgra32r; //----alpha_mask_bgra32r
|
||||
typedef alpha_mask_u8<4, 1> alpha_mask_bgra32g; //----alpha_mask_bgra32g
|
||||
typedef alpha_mask_u8<4, 0> alpha_mask_bgra32b; //----alpha_mask_bgra32b
|
||||
typedef alpha_mask_u8<4, 3> alpha_mask_bgra32a; //----alpha_mask_bgra32a
|
||||
|
||||
typedef alpha_mask_u8<4, 3> alpha_mask_abgr32r; //----alpha_mask_abgr32r
|
||||
typedef alpha_mask_u8<4, 2> alpha_mask_abgr32g; //----alpha_mask_abgr32g
|
||||
typedef alpha_mask_u8<4, 1> alpha_mask_abgr32b; //----alpha_mask_abgr32b
|
||||
typedef alpha_mask_u8<4, 0> alpha_mask_abgr32a; //----alpha_mask_abgr32a
|
||||
|
||||
typedef alpha_mask_u8<3, 0, rgb_to_gray_mask_u8<0, 1, 2> > alpha_mask_rgb24gray; //----alpha_mask_rgb24gray
|
||||
typedef alpha_mask_u8<3, 0, rgb_to_gray_mask_u8<2, 1, 0> > alpha_mask_bgr24gray; //----alpha_mask_bgr24gray
|
||||
typedef alpha_mask_u8<4, 0, rgb_to_gray_mask_u8<0, 1, 2> > alpha_mask_rgba32gray; //----alpha_mask_rgba32gray
|
||||
typedef alpha_mask_u8<4, 1, rgb_to_gray_mask_u8<0, 1, 2> > alpha_mask_argb32gray; //----alpha_mask_argb32gray
|
||||
typedef alpha_mask_u8<4, 0, rgb_to_gray_mask_u8<2, 1, 0> > alpha_mask_bgra32gray; //----alpha_mask_bgra32gray
|
||||
typedef alpha_mask_u8<4, 1, rgb_to_gray_mask_u8<2, 1, 0> > alpha_mask_abgr32gray; //----alpha_mask_abgr32gray
|
||||
|
||||
|
||||
|
||||
//==========================================================amask_no_clip_u8
|
||||
template<unsigned Step=1, unsigned Offset=0, class MaskF=one_component_mask_u8>
|
||||
class amask_no_clip_u8
|
||||
{
|
||||
public:
|
||||
typedef int8u cover_type;
|
||||
typedef amask_no_clip_u8<Step, Offset, MaskF> self_type;
|
||||
enum cover_scale_e
|
||||
{
|
||||
cover_shift = 8,
|
||||
cover_none = 0,
|
||||
cover_full = 255
|
||||
};
|
||||
|
||||
amask_no_clip_u8() : m_rbuf(0) {}
|
||||
explicit amask_no_clip_u8(rendering_buffer& rbuf) : m_rbuf(&rbuf) {}
|
||||
|
||||
void attach(rendering_buffer& rbuf) { m_rbuf = &rbuf; }
|
||||
|
||||
MaskF& mask_function() { return m_mask_function; }
|
||||
const MaskF& mask_function() const { return m_mask_function; }
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
cover_type pixel(int x, int y) const
|
||||
{
|
||||
return (cover_type)m_mask_function.calculate(
|
||||
m_rbuf->row_ptr(y) + x * Step + Offset);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
cover_type combine_pixel(int x, int y, cover_type val) const
|
||||
{
|
||||
return (cover_type)((cover_full + val *
|
||||
m_mask_function.calculate(
|
||||
m_rbuf->row_ptr(y) + x * Step + Offset)) >>
|
||||
cover_shift);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void fill_hspan(int x, int y, cover_type* dst, int num_pix) const
|
||||
{
|
||||
const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
|
||||
do
|
||||
{
|
||||
*dst++ = (cover_type)m_mask_function.calculate(mask);
|
||||
mask += Step;
|
||||
}
|
||||
while(--num_pix);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void combine_hspan(int x, int y, cover_type* dst, int num_pix) const
|
||||
{
|
||||
const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
|
||||
do
|
||||
{
|
||||
*dst = (cover_type)((cover_full + (*dst) *
|
||||
m_mask_function.calculate(mask)) >>
|
||||
cover_shift);
|
||||
++dst;
|
||||
mask += Step;
|
||||
}
|
||||
while(--num_pix);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void fill_vspan(int x, int y, cover_type* dst, int num_pix) const
|
||||
{
|
||||
const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
|
||||
do
|
||||
{
|
||||
*dst++ = (cover_type)m_mask_function.calculate(mask);
|
||||
mask += m_rbuf->stride();
|
||||
}
|
||||
while(--num_pix);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void combine_vspan(int x, int y, cover_type* dst, int num_pix) const
|
||||
{
|
||||
const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset;
|
||||
do
|
||||
{
|
||||
*dst = (cover_type)((cover_full + (*dst) *
|
||||
m_mask_function.calculate(mask)) >>
|
||||
cover_shift);
|
||||
++dst;
|
||||
mask += m_rbuf->stride();
|
||||
}
|
||||
while(--num_pix);
|
||||
}
|
||||
|
||||
private:
|
||||
amask_no_clip_u8(const self_type&);
|
||||
const self_type& operator = (const self_type&);
|
||||
|
||||
rendering_buffer* m_rbuf;
|
||||
MaskF m_mask_function;
|
||||
};
|
||||
|
||||
|
||||
typedef amask_no_clip_u8<1, 0> amask_no_clip_gray8; //----amask_no_clip_gray8
|
||||
|
||||
typedef amask_no_clip_u8<3, 0> amask_no_clip_rgb24r; //----amask_no_clip_rgb24r
|
||||
typedef amask_no_clip_u8<3, 1> amask_no_clip_rgb24g; //----amask_no_clip_rgb24g
|
||||
typedef amask_no_clip_u8<3, 2> amask_no_clip_rgb24b; //----amask_no_clip_rgb24b
|
||||
|
||||
typedef amask_no_clip_u8<3, 2> amask_no_clip_bgr24r; //----amask_no_clip_bgr24r
|
||||
typedef amask_no_clip_u8<3, 1> amask_no_clip_bgr24g; //----amask_no_clip_bgr24g
|
||||
typedef amask_no_clip_u8<3, 0> amask_no_clip_bgr24b; //----amask_no_clip_bgr24b
|
||||
|
||||
typedef amask_no_clip_u8<4, 0> amask_no_clip_rgba32r; //----amask_no_clip_rgba32r
|
||||
typedef amask_no_clip_u8<4, 1> amask_no_clip_rgba32g; //----amask_no_clip_rgba32g
|
||||
typedef amask_no_clip_u8<4, 2> amask_no_clip_rgba32b; //----amask_no_clip_rgba32b
|
||||
typedef amask_no_clip_u8<4, 3> amask_no_clip_rgba32a; //----amask_no_clip_rgba32a
|
||||
|
||||
typedef amask_no_clip_u8<4, 1> amask_no_clip_argb32r; //----amask_no_clip_argb32r
|
||||
typedef amask_no_clip_u8<4, 2> amask_no_clip_argb32g; //----amask_no_clip_argb32g
|
||||
typedef amask_no_clip_u8<4, 3> amask_no_clip_argb32b; //----amask_no_clip_argb32b
|
||||
typedef amask_no_clip_u8<4, 0> amask_no_clip_argb32a; //----amask_no_clip_argb32a
|
||||
|
||||
typedef amask_no_clip_u8<4, 2> amask_no_clip_bgra32r; //----amask_no_clip_bgra32r
|
||||
typedef amask_no_clip_u8<4, 1> amask_no_clip_bgra32g; //----amask_no_clip_bgra32g
|
||||
typedef amask_no_clip_u8<4, 0> amask_no_clip_bgra32b; //----amask_no_clip_bgra32b
|
||||
typedef amask_no_clip_u8<4, 3> amask_no_clip_bgra32a; //----amask_no_clip_bgra32a
|
||||
|
||||
typedef amask_no_clip_u8<4, 3> amask_no_clip_abgr32r; //----amask_no_clip_abgr32r
|
||||
typedef amask_no_clip_u8<4, 2> amask_no_clip_abgr32g; //----amask_no_clip_abgr32g
|
||||
typedef amask_no_clip_u8<4, 1> amask_no_clip_abgr32b; //----amask_no_clip_abgr32b
|
||||
typedef amask_no_clip_u8<4, 0> amask_no_clip_abgr32a; //----amask_no_clip_abgr32a
|
||||
|
||||
typedef amask_no_clip_u8<3, 0, rgb_to_gray_mask_u8<0, 1, 2> > amask_no_clip_rgb24gray; //----amask_no_clip_rgb24gray
|
||||
typedef amask_no_clip_u8<3, 0, rgb_to_gray_mask_u8<2, 1, 0> > amask_no_clip_bgr24gray; //----amask_no_clip_bgr24gray
|
||||
typedef amask_no_clip_u8<4, 0, rgb_to_gray_mask_u8<0, 1, 2> > amask_no_clip_rgba32gray; //----amask_no_clip_rgba32gray
|
||||
typedef amask_no_clip_u8<4, 1, rgb_to_gray_mask_u8<0, 1, 2> > amask_no_clip_argb32gray; //----amask_no_clip_argb32gray
|
||||
typedef amask_no_clip_u8<4, 0, rgb_to_gray_mask_u8<2, 1, 0> > amask_no_clip_bgra32gray; //----amask_no_clip_bgra32gray
|
||||
typedef amask_no_clip_u8<4, 1, rgb_to_gray_mask_u8<2, 1, 0> > amask_no_clip_abgr32gray; //----amask_no_clip_abgr32gray
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
73
dep/agg/include/agg_arc.h
Normal file
73
dep/agg/include/agg_arc.h
Normal file
@@ -0,0 +1,73 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.4
|
||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all copies.
|
||||
// This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Arc vertex generator
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_ARC_INCLUDED
|
||||
#define AGG_ARC_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//=====================================================================arc
|
||||
//
|
||||
// See Implementation agg_arc.cpp
|
||||
//
|
||||
class arc
|
||||
{
|
||||
public:
|
||||
arc() : m_scale(1.0), m_initialized(false) {}
|
||||
arc(double x, double y,
|
||||
double rx, double ry,
|
||||
double a1, double a2,
|
||||
bool ccw=true);
|
||||
|
||||
void init(double x, double y,
|
||||
double rx, double ry,
|
||||
double a1, double a2,
|
||||
bool ccw=true);
|
||||
|
||||
void approximation_scale(double s);
|
||||
double approximation_scale() const { return m_scale; }
|
||||
|
||||
void rewind(unsigned);
|
||||
unsigned vertex(double* x, double* y);
|
||||
|
||||
private:
|
||||
void normalize(double a1, double a2, bool ccw);
|
||||
|
||||
double m_x;
|
||||
double m_y;
|
||||
double m_rx;
|
||||
double m_ry;
|
||||
double m_angle;
|
||||
double m_start;
|
||||
double m_end;
|
||||
double m_scale;
|
||||
double m_da;
|
||||
bool m_ccw;
|
||||
bool m_initialized;
|
||||
unsigned m_path_cmd;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
1119
dep/agg/include/agg_array.h
Normal file
1119
dep/agg/include/agg_array.h
Normal file
File diff suppressed because it is too large
Load Diff
82
dep/agg/include/agg_arrowhead.h
Normal file
82
dep/agg/include/agg_arrowhead.h
Normal file
@@ -0,0 +1,82 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.4
|
||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all copies.
|
||||
// This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Simple arrowhead/arrowtail generator
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
#ifndef AGG_ARROWHEAD_INCLUDED
|
||||
#define AGG_ARROWHEAD_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//===============================================================arrowhead
|
||||
//
|
||||
// See implementation agg_arrowhead.cpp
|
||||
//
|
||||
class arrowhead
|
||||
{
|
||||
public:
|
||||
arrowhead();
|
||||
|
||||
void head(double d1, double d2, double d3, double d4)
|
||||
{
|
||||
m_head_d1 = d1;
|
||||
m_head_d2 = d2;
|
||||
m_head_d3 = d3;
|
||||
m_head_d4 = d4;
|
||||
m_head_flag = true;
|
||||
}
|
||||
|
||||
void head() { m_head_flag = true; }
|
||||
void no_head() { m_head_flag = false; }
|
||||
|
||||
void tail(double d1, double d2, double d3, double d4)
|
||||
{
|
||||
m_tail_d1 = d1;
|
||||
m_tail_d2 = d2;
|
||||
m_tail_d3 = d3;
|
||||
m_tail_d4 = d4;
|
||||
m_tail_flag = true;
|
||||
}
|
||||
|
||||
void tail() { m_tail_flag = true; }
|
||||
void no_tail() { m_tail_flag = false; }
|
||||
|
||||
void rewind(unsigned path_id);
|
||||
unsigned vertex(double* x, double* y);
|
||||
|
||||
private:
|
||||
double m_head_d1;
|
||||
double m_head_d2;
|
||||
double m_head_d3;
|
||||
double m_head_d4;
|
||||
double m_tail_d1;
|
||||
double m_tail_d2;
|
||||
double m_tail_d3;
|
||||
double m_tail_d4;
|
||||
bool m_head_flag;
|
||||
bool m_tail_flag;
|
||||
double m_coord[16];
|
||||
unsigned m_cmd[8];
|
||||
unsigned m_curr_id;
|
||||
unsigned m_curr_coord;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
574
dep/agg/include/agg_basics.h
Normal file
574
dep/agg/include/agg_basics.h
Normal file
@@ -0,0 +1,574 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.4
|
||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all copies.
|
||||
// This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_BASICS_INCLUDED
|
||||
#define AGG_BASICS_INCLUDED
|
||||
|
||||
#include <cmath>
|
||||
#include "agg_config.h"
|
||||
|
||||
//---------------------------------------------------------AGG_CUSTOM_ALLOCATOR
|
||||
#ifdef AGG_CUSTOM_ALLOCATOR
|
||||
#include "agg_allocator.h"
|
||||
#else
|
||||
namespace agg
|
||||
{
|
||||
// The policy of all AGG containers and memory allocation strategy
|
||||
// in general is that no allocated data requires explicit construction.
|
||||
// It means that the allocator can be really simple; you can even
|
||||
// replace new/delete to malloc/free. The constructors and destructors
|
||||
// won't be called in this case, however everything will remain working.
|
||||
// The second argument of deallocate() is the size of the allocated
|
||||
// block. You can use this information if you wish.
|
||||
//------------------------------------------------------------pod_allocator
|
||||
template<class T> struct pod_allocator
|
||||
{
|
||||
static T* allocate(unsigned num) { return new T [num]; }
|
||||
static void deallocate(T* ptr, unsigned) { delete [] ptr; }
|
||||
};
|
||||
|
||||
// Single object allocator. It's also can be replaced with your custom
|
||||
// allocator. The difference is that it can only allocate a single
|
||||
// object and the constructor and destructor must be called.
|
||||
// In AGG there is no need to allocate an array of objects with
|
||||
// calling their constructors (only single ones). So that, if you
|
||||
// replace these new/delete to malloc/free make sure that the in-place
|
||||
// new is called and take care of calling the destructor too.
|
||||
//------------------------------------------------------------obj_allocator
|
||||
template<class T> struct obj_allocator
|
||||
{
|
||||
static T* allocate() { return new T; }
|
||||
static void deallocate(T* ptr) { delete ptr; }
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//-------------------------------------------------------- Default basic types
|
||||
//
|
||||
// If the compiler has different capacity of the basic types you can redefine
|
||||
// them via the compiler command line or by generating agg_config.h that is
|
||||
// empty by default.
|
||||
//
|
||||
#ifndef AGG_INT8
|
||||
#define AGG_INT8 signed char
|
||||
#endif
|
||||
|
||||
#ifndef AGG_INT8U
|
||||
#define AGG_INT8U unsigned char
|
||||
#endif
|
||||
|
||||
#ifndef AGG_INT16
|
||||
#define AGG_INT16 short
|
||||
#endif
|
||||
|
||||
#ifndef AGG_INT16U
|
||||
#define AGG_INT16U unsigned short
|
||||
#endif
|
||||
|
||||
#ifndef AGG_INT32
|
||||
#define AGG_INT32 int
|
||||
#endif
|
||||
|
||||
#ifndef AGG_INT32U
|
||||
#define AGG_INT32U unsigned
|
||||
#endif
|
||||
|
||||
#ifndef AGG_INT64
|
||||
#if defined(_MSC_VER) || defined(__BORLANDC__)
|
||||
#define AGG_INT64 signed __int64
|
||||
#else
|
||||
#define AGG_INT64 signed long long
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef AGG_INT64U
|
||||
#if defined(_MSC_VER) || defined(__BORLANDC__)
|
||||
#define AGG_INT64U unsigned __int64
|
||||
#else
|
||||
#define AGG_INT64U unsigned long long
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//------------------------------------------------ Some fixes for MS Visual C++
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(disable:4786) // Identifier was truncated...
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define AGG_INLINE __forceinline
|
||||
#else
|
||||
#define AGG_INLINE inline
|
||||
#endif
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//-------------------------------------------------------------------------
|
||||
typedef AGG_INT8 int8; //----int8
|
||||
typedef AGG_INT8U int8u; //----int8u
|
||||
typedef AGG_INT16 int16; //----int16
|
||||
typedef AGG_INT16U int16u; //----int16u
|
||||
typedef AGG_INT32 int32; //----int32
|
||||
typedef AGG_INT32U int32u; //----int32u
|
||||
typedef AGG_INT64 int64; //----int64
|
||||
typedef AGG_INT64U int64u; //----int64u
|
||||
|
||||
#if defined(AGG_FISTP)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4035) //Disable warning "no return value"
|
||||
AGG_INLINE int iround(double v) //-------iround
|
||||
{
|
||||
int t;
|
||||
__asm fld qword ptr [v]
|
||||
__asm fistp dword ptr [t]
|
||||
__asm mov eax, dword ptr [t]
|
||||
}
|
||||
AGG_INLINE unsigned uround(double v) //-------uround
|
||||
{
|
||||
unsigned t;
|
||||
__asm fld qword ptr [v]
|
||||
__asm fistp dword ptr [t]
|
||||
__asm mov eax, dword ptr [t]
|
||||
}
|
||||
#pragma warning(pop)
|
||||
AGG_INLINE int ifloor(double v)
|
||||
{
|
||||
return int(floor(v));
|
||||
}
|
||||
AGG_INLINE unsigned ufloor(double v) //-------ufloor
|
||||
{
|
||||
return unsigned(floor(v));
|
||||
}
|
||||
AGG_INLINE int iceil(double v)
|
||||
{
|
||||
return int(ceil(v));
|
||||
}
|
||||
AGG_INLINE unsigned uceil(double v) //--------uceil
|
||||
{
|
||||
return unsigned(ceil(v));
|
||||
}
|
||||
#elif defined(AGG_QIFIST)
|
||||
AGG_INLINE int iround(double v)
|
||||
{
|
||||
return int(v);
|
||||
}
|
||||
AGG_INLINE int uround(double v)
|
||||
{
|
||||
return unsigned(v);
|
||||
}
|
||||
AGG_INLINE int ifloor(double v)
|
||||
{
|
||||
return int(std::floor(v));
|
||||
}
|
||||
AGG_INLINE unsigned ufloor(double v)
|
||||
{
|
||||
return unsigned(std::floor(v));
|
||||
}
|
||||
AGG_INLINE int iceil(double v)
|
||||
{
|
||||
return int(std::ceil(v));
|
||||
}
|
||||
AGG_INLINE unsigned uceil(double v)
|
||||
{
|
||||
return unsigned(std::ceil(v));
|
||||
}
|
||||
#else
|
||||
AGG_INLINE int iround(double v)
|
||||
{
|
||||
return int((v < 0.0) ? v - 0.5 : v + 0.5);
|
||||
}
|
||||
AGG_INLINE int uround(double v)
|
||||
{
|
||||
return unsigned(v + 0.5);
|
||||
}
|
||||
AGG_INLINE int ifloor(double v)
|
||||
{
|
||||
int i = int(v);
|
||||
return i - (i > v);
|
||||
}
|
||||
AGG_INLINE unsigned ufloor(double v)
|
||||
{
|
||||
return unsigned(v);
|
||||
}
|
||||
AGG_INLINE int iceil(double v)
|
||||
{
|
||||
return int(std::ceil(v));
|
||||
}
|
||||
AGG_INLINE unsigned uceil(double v)
|
||||
{
|
||||
return unsigned(std::ceil(v));
|
||||
}
|
||||
#endif
|
||||
|
||||
//---------------------------------------------------------------saturation
|
||||
template<int Limit> struct saturation
|
||||
{
|
||||
AGG_INLINE static int iround(double v)
|
||||
{
|
||||
if(v < double(-Limit)) return -Limit;
|
||||
if(v > double( Limit)) return Limit;
|
||||
return agg::iround(v);
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------mul_one
|
||||
template<unsigned Shift> struct mul_one
|
||||
{
|
||||
AGG_INLINE static unsigned mul(unsigned a, unsigned b)
|
||||
{
|
||||
unsigned q = a * b + (1 << (Shift-1));
|
||||
return (q + (q >> Shift)) >> Shift;
|
||||
}
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
typedef unsigned char cover_type; //----cover_type
|
||||
enum cover_scale_e
|
||||
{
|
||||
cover_shift = 8, //----cover_shift
|
||||
cover_size = 1 << cover_shift, //----cover_size
|
||||
cover_mask = cover_size - 1, //----cover_mask
|
||||
cover_none = 0, //----cover_none
|
||||
cover_full = cover_mask //----cover_full
|
||||
};
|
||||
|
||||
//----------------------------------------------------poly_subpixel_scale_e
|
||||
// These constants determine the subpixel accuracy, to be more precise,
|
||||
// the number of bits of the fractional part of the coordinates.
|
||||
// The possible coordinate capacity in bits can be calculated by formula:
|
||||
// sizeof(int) * 8 - poly_subpixel_shift, i.e, for 32-bit integers and
|
||||
// 8-bits fractional part the capacity is 24 bits.
|
||||
enum poly_subpixel_scale_e
|
||||
{
|
||||
poly_subpixel_shift = 8, //----poly_subpixel_shift
|
||||
poly_subpixel_scale = 1<<poly_subpixel_shift, //----poly_subpixel_scale
|
||||
poly_subpixel_mask = poly_subpixel_scale-1 //----poly_subpixel_mask
|
||||
};
|
||||
|
||||
//----------------------------------------------------------filling_rule_e
|
||||
enum filling_rule_e
|
||||
{
|
||||
fill_non_zero,
|
||||
fill_even_odd
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------pi
|
||||
const double pi = 3.14159265358979323846;
|
||||
|
||||
//------------------------------------------------------------------deg2rad
|
||||
inline double deg2rad(double deg)
|
||||
{
|
||||
return deg * pi / 180.0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------rad2deg
|
||||
inline double rad2deg(double rad)
|
||||
{
|
||||
return rad * 180.0 / pi;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------rect_base
|
||||
template<class T> struct rect_base
|
||||
{
|
||||
typedef T value_type;
|
||||
typedef rect_base<T> self_type;
|
||||
T x1, y1, x2, y2;
|
||||
|
||||
rect_base() {}
|
||||
rect_base(T x1_, T y1_, T x2_, T y2_) :
|
||||
x1(x1_), y1(y1_), x2(x2_), y2(y2_) {}
|
||||
|
||||
void init(T x1_, T y1_, T x2_, T y2_)
|
||||
{
|
||||
x1 = x1_; y1 = y1_; x2 = x2_; y2 = y2_;
|
||||
}
|
||||
|
||||
const self_type& normalize()
|
||||
{
|
||||
T t;
|
||||
if(x1 > x2) { t = x1; x1 = x2; x2 = t; }
|
||||
if(y1 > y2) { t = y1; y1 = y2; y2 = t; }
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool clip(const self_type& r)
|
||||
{
|
||||
if(x2 > r.x2) x2 = r.x2;
|
||||
if(y2 > r.y2) y2 = r.y2;
|
||||
if(x1 < r.x1) x1 = r.x1;
|
||||
if(y1 < r.y1) y1 = r.y1;
|
||||
return x1 <= x2 && y1 <= y2;
|
||||
}
|
||||
|
||||
bool is_valid() const
|
||||
{
|
||||
return x1 <= x2 && y1 <= y2;
|
||||
}
|
||||
|
||||
bool hit_test(T x, T y) const
|
||||
{
|
||||
return (x >= x1 && x <= x2 && y >= y1 && y <= y2);
|
||||
}
|
||||
|
||||
bool overlaps(const self_type& r) const
|
||||
{
|
||||
return !(r.x1 > x2 || r.x2 < x1
|
||||
|| r.y1 > y2 || r.y2 < y1);
|
||||
}
|
||||
};
|
||||
|
||||
//-----------------------------------------------------intersect_rectangles
|
||||
template<class Rect>
|
||||
inline Rect intersect_rectangles(const Rect& r1, const Rect& r2)
|
||||
{
|
||||
Rect r = r1;
|
||||
|
||||
// First process x2,y2 because the other order
|
||||
// results in Internal Compiler Error under
|
||||
// Microsoft Visual C++ .NET 2003 69462-335-0000007-18038 in
|
||||
// case of "Maximize Speed" optimization option.
|
||||
//-----------------
|
||||
if(r.x2 > r2.x2) r.x2 = r2.x2;
|
||||
if(r.y2 > r2.y2) r.y2 = r2.y2;
|
||||
if(r.x1 < r2.x1) r.x1 = r2.x1;
|
||||
if(r.y1 < r2.y1) r.y1 = r2.y1;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------unite_rectangles
|
||||
template<class Rect>
|
||||
inline Rect unite_rectangles(const Rect& r1, const Rect& r2)
|
||||
{
|
||||
Rect r = r1;
|
||||
if(r.x2 < r2.x2) r.x2 = r2.x2;
|
||||
if(r.y2 < r2.y2) r.y2 = r2.y2;
|
||||
if(r.x1 > r2.x1) r.x1 = r2.x1;
|
||||
if(r.y1 > r2.y1) r.y1 = r2.y1;
|
||||
return r;
|
||||
}
|
||||
|
||||
typedef rect_base<int> rect_i; //----rect_i
|
||||
typedef rect_base<float> rect_f; //----rect_f
|
||||
typedef rect_base<double> rect_d; //----rect_d
|
||||
|
||||
//---------------------------------------------------------path_commands_e
|
||||
enum path_commands_e
|
||||
{
|
||||
path_cmd_stop = 0, //----path_cmd_stop
|
||||
path_cmd_move_to = 1, //----path_cmd_move_to
|
||||
path_cmd_line_to = 2, //----path_cmd_line_to
|
||||
path_cmd_curve3 = 3, //----path_cmd_curve3
|
||||
path_cmd_curve4 = 4, //----path_cmd_curve4
|
||||
path_cmd_curveN = 5, //----path_cmd_curveN
|
||||
path_cmd_catrom = 6, //----path_cmd_catrom
|
||||
path_cmd_ubspline = 7, //----path_cmd_ubspline
|
||||
path_cmd_end_poly = 0x0F, //----path_cmd_end_poly
|
||||
path_cmd_mask = 0x0F //----path_cmd_mask
|
||||
};
|
||||
|
||||
//------------------------------------------------------------path_flags_e
|
||||
enum path_flags_e
|
||||
{
|
||||
path_flags_none = 0, //----path_flags_none
|
||||
path_flags_ccw = 0x10, //----path_flags_ccw
|
||||
path_flags_cw = 0x20, //----path_flags_cw
|
||||
path_flags_close = 0x40, //----path_flags_close
|
||||
path_flags_mask = 0xF0 //----path_flags_mask
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------is_vertex
|
||||
inline bool is_vertex(unsigned c)
|
||||
{
|
||||
return c >= path_cmd_move_to && c < path_cmd_end_poly;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------is_drawing
|
||||
inline bool is_drawing(unsigned c)
|
||||
{
|
||||
return c >= path_cmd_line_to && c < path_cmd_end_poly;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------is_stop
|
||||
inline bool is_stop(unsigned c)
|
||||
{
|
||||
return c == path_cmd_stop;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------is_move_to
|
||||
inline bool is_move_to(unsigned c)
|
||||
{
|
||||
return c == path_cmd_move_to;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------is_line_to
|
||||
inline bool is_line_to(unsigned c)
|
||||
{
|
||||
return c == path_cmd_line_to;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------is_curve
|
||||
inline bool is_curve(unsigned c)
|
||||
{
|
||||
return c == path_cmd_curve3 || c == path_cmd_curve4;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------is_curve3
|
||||
inline bool is_curve3(unsigned c)
|
||||
{
|
||||
return c == path_cmd_curve3;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------is_curve4
|
||||
inline bool is_curve4(unsigned c)
|
||||
{
|
||||
return c == path_cmd_curve4;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------is_end_poly
|
||||
inline bool is_end_poly(unsigned c)
|
||||
{
|
||||
return (c & path_cmd_mask) == path_cmd_end_poly;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------is_close
|
||||
inline bool is_close(unsigned c)
|
||||
{
|
||||
return (c & ~(path_flags_cw | path_flags_ccw)) ==
|
||||
(path_cmd_end_poly | path_flags_close);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------is_next_poly
|
||||
inline bool is_next_poly(unsigned c)
|
||||
{
|
||||
return is_stop(c) || is_move_to(c) || is_end_poly(c);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------is_cw
|
||||
inline bool is_cw(unsigned c)
|
||||
{
|
||||
return (c & path_flags_cw) != 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------is_ccw
|
||||
inline bool is_ccw(unsigned c)
|
||||
{
|
||||
return (c & path_flags_ccw) != 0;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------is_oriented
|
||||
inline bool is_oriented(unsigned c)
|
||||
{
|
||||
return (c & (path_flags_cw | path_flags_ccw)) != 0;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------is_closed
|
||||
inline bool is_closed(unsigned c)
|
||||
{
|
||||
return (c & path_flags_close) != 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------get_close_flag
|
||||
inline unsigned get_close_flag(unsigned c)
|
||||
{
|
||||
return c & path_flags_close;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------clear_orientation
|
||||
inline unsigned clear_orientation(unsigned c)
|
||||
{
|
||||
return c & ~(path_flags_cw | path_flags_ccw);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------get_orientation
|
||||
inline unsigned get_orientation(unsigned c)
|
||||
{
|
||||
return c & (path_flags_cw | path_flags_ccw);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------set_orientation
|
||||
inline unsigned set_orientation(unsigned c, unsigned o)
|
||||
{
|
||||
return clear_orientation(c) | o;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------point_base
|
||||
template<class T> struct point_base
|
||||
{
|
||||
typedef T value_type;
|
||||
T x,y;
|
||||
point_base() {}
|
||||
point_base(T x_, T y_) : x(x_), y(y_) {}
|
||||
};
|
||||
typedef point_base<int> point_i; //-----point_i
|
||||
typedef point_base<float> point_f; //-----point_f
|
||||
typedef point_base<double> point_d; //-----point_d
|
||||
|
||||
//-------------------------------------------------------------vertex_base
|
||||
template<class T> struct vertex_base
|
||||
{
|
||||
typedef T value_type;
|
||||
T x,y;
|
||||
unsigned cmd;
|
||||
vertex_base() {}
|
||||
vertex_base(T x_, T y_, unsigned cmd_) : x(x_), y(y_), cmd(cmd_) {}
|
||||
};
|
||||
typedef vertex_base<int> vertex_i; //-----vertex_i
|
||||
typedef vertex_base<float> vertex_f; //-----vertex_f
|
||||
typedef vertex_base<double> vertex_d; //-----vertex_d
|
||||
|
||||
//----------------------------------------------------------------row_info
|
||||
template<class T> struct row_info
|
||||
{
|
||||
int x1, x2;
|
||||
T* ptr;
|
||||
row_info() {}
|
||||
row_info(int x1_, int x2_, T* ptr_) : x1(x1_), x2(x2_), ptr(ptr_) {}
|
||||
};
|
||||
|
||||
//----------------------------------------------------------const_row_info
|
||||
template<class T> struct const_row_info
|
||||
{
|
||||
int x1, x2;
|
||||
const T* ptr;
|
||||
const_row_info() {}
|
||||
const_row_info(int x1_, int x2_, const T* ptr_) :
|
||||
x1(x1_), x2(x2_), ptr(ptr_) {}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------is_equal_eps
|
||||
template<class T> inline bool is_equal_eps(T v1, T v2, T epsilon)
|
||||
{
|
||||
bool neg1 = v1 < 0.0;
|
||||
bool neg2 = v2 < 0.0;
|
||||
|
||||
if (neg1 != neg2)
|
||||
return std::fabs(v1) < epsilon && std::fabs(v2) < epsilon;
|
||||
|
||||
int int1, int2;
|
||||
std::frexp(v1, &int1);
|
||||
std::frexp(v2, &int2);
|
||||
int min12 = int1 < int2 ? int1 : int2;
|
||||
|
||||
v1 = std::ldexp(v1, -min12);
|
||||
v2 = std::ldexp(v2, -min12);
|
||||
|
||||
return std::fabs(v1 - v2) < epsilon;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
159
dep/agg/include/agg_bezier_arc.h
Normal file
159
dep/agg/include/agg_bezier_arc.h
Normal file
@@ -0,0 +1,159 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.4
|
||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all copies.
|
||||
// This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Arc generator. Produces at most 4 consecutive cubic bezier curves, i.e.,
|
||||
// 4, 7, 10, or 13 vertices.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_BEZIER_ARC_INCLUDED
|
||||
#define AGG_BEZIER_ARC_INCLUDED
|
||||
|
||||
#include "agg_conv_transform.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
void arc_to_bezier(double cx, double cy, double rx, double ry,
|
||||
double start_angle, double sweep_angle,
|
||||
double* curve);
|
||||
|
||||
|
||||
//==============================================================bezier_arc
|
||||
//
|
||||
// See implemantaion agg_bezier_arc.cpp
|
||||
//
|
||||
class bezier_arc
|
||||
{
|
||||
public:
|
||||
//--------------------------------------------------------------------
|
||||
bezier_arc() : m_vertex(26), m_num_vertices(0), m_cmd(path_cmd_line_to) {}
|
||||
bezier_arc(double x, double y,
|
||||
double rx, double ry,
|
||||
double start_angle,
|
||||
double sweep_angle)
|
||||
{
|
||||
init(x, y, rx, ry, start_angle, sweep_angle);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void init(double x, double y,
|
||||
double rx, double ry,
|
||||
double start_angle,
|
||||
double sweep_angle);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void rewind(unsigned)
|
||||
{
|
||||
m_vertex = 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
unsigned vertex(double* x, double* y)
|
||||
{
|
||||
if(m_vertex >= m_num_vertices) return path_cmd_stop;
|
||||
*x = m_vertices[m_vertex];
|
||||
*y = m_vertices[m_vertex + 1];
|
||||
m_vertex += 2;
|
||||
return (m_vertex == 2) ? unsigned(path_cmd_move_to) : m_cmd;
|
||||
}
|
||||
|
||||
// Supplemantary functions. num_vertices() actually returns doubled
|
||||
// number of vertices. That is, for 1 vertex it returns 2.
|
||||
//--------------------------------------------------------------------
|
||||
unsigned num_vertices() const { return m_num_vertices; }
|
||||
const double* vertices() const { return m_vertices; }
|
||||
double* vertices() { return m_vertices; }
|
||||
|
||||
private:
|
||||
unsigned m_vertex;
|
||||
unsigned m_num_vertices;
|
||||
double m_vertices[26];
|
||||
unsigned m_cmd;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//==========================================================bezier_arc_svg
|
||||
// Compute an SVG-style bezier arc.
|
||||
//
|
||||
// Computes an elliptical arc from (x1, y1) to (x2, y2). The size and
|
||||
// orientation of the ellipse are defined by two radii (rx, ry)
|
||||
// and an x-axis-rotation, which indicates how the ellipse as a whole
|
||||
// is rotated relative to the current coordinate system. The center
|
||||
// (cx, cy) of the ellipse is calculated automatically to satisfy the
|
||||
// constraints imposed by the other parameters.
|
||||
// large-arc-flag and sweep-flag contribute to the automatic calculations
|
||||
// and help determine how the arc is drawn.
|
||||
class bezier_arc_svg
|
||||
{
|
||||
public:
|
||||
//--------------------------------------------------------------------
|
||||
bezier_arc_svg() : m_arc(), m_radii_ok(false) {}
|
||||
|
||||
bezier_arc_svg(double x1, double y1,
|
||||
double rx, double ry,
|
||||
double angle,
|
||||
bool large_arc_flag,
|
||||
bool sweep_flag,
|
||||
double x2, double y2) :
|
||||
m_arc(), m_radii_ok(false)
|
||||
{
|
||||
init(x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void init(double x1, double y1,
|
||||
double rx, double ry,
|
||||
double angle,
|
||||
bool large_arc_flag,
|
||||
bool sweep_flag,
|
||||
double x2, double y2);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
bool radii_ok() const { return m_radii_ok; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void rewind(unsigned)
|
||||
{
|
||||
m_arc.rewind(0);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
unsigned vertex(double* x, double* y)
|
||||
{
|
||||
return m_arc.vertex(x, y);
|
||||
}
|
||||
|
||||
// Supplemantary functions. num_vertices() actually returns doubled
|
||||
// number of vertices. That is, for 1 vertex it returns 2.
|
||||
//--------------------------------------------------------------------
|
||||
unsigned num_vertices() const { return m_arc.num_vertices(); }
|
||||
const double* vertices() const { return m_arc.vertices(); }
|
||||
double* vertices() { return m_arc.vertices(); }
|
||||
|
||||
private:
|
||||
bezier_arc m_arc;
|
||||
bool m_radii_ok;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
54
dep/agg/include/agg_bitset_iterator.h
Normal file
54
dep/agg/include/agg_bitset_iterator.h
Normal file
@@ -0,0 +1,54 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.4
|
||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all copies.
|
||||
// This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_BITSET_ITERATOR_INCLUDED
|
||||
#define AGG_BITSET_ITERATOR_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
class bitset_iterator
|
||||
{
|
||||
public:
|
||||
bitset_iterator(const int8u* bits, unsigned offset = 0) :
|
||||
m_bits(bits + (offset >> 3)),
|
||||
m_mask(0x80 >> (offset & 7))
|
||||
{}
|
||||
|
||||
void operator ++ ()
|
||||
{
|
||||
m_mask >>= 1;
|
||||
if(m_mask == 0)
|
||||
{
|
||||
++m_bits;
|
||||
m_mask = 0x80;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned bit() const
|
||||
{
|
||||
return (*m_bits) & m_mask;
|
||||
}
|
||||
|
||||
private:
|
||||
const int8u* m_bits;
|
||||
int8u m_mask;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
1505
dep/agg/include/agg_blur.h
Normal file
1505
dep/agg/include/agg_blur.h
Normal file
File diff suppressed because it is too large
Load Diff
116
dep/agg/include/agg_bounding_rect.h
Normal file
116
dep/agg/include/agg_bounding_rect.h
Normal file
@@ -0,0 +1,116 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.4
|
||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all copies.
|
||||
// This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// bounding_rect function template
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
#ifndef AGG_BOUNDING_RECT_INCLUDED
|
||||
#define AGG_BOUNDING_RECT_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//-----------------------------------------------------------bounding_rect
|
||||
template<class VertexSource, class GetId, class CoordT>
|
||||
bool bounding_rect(VertexSource& vs, GetId& gi,
|
||||
unsigned start, unsigned num,
|
||||
CoordT* x1, CoordT* y1, CoordT* x2, CoordT* y2)
|
||||
{
|
||||
unsigned i;
|
||||
double x;
|
||||
double y;
|
||||
bool first = true;
|
||||
|
||||
*x1 = CoordT(1);
|
||||
*y1 = CoordT(1);
|
||||
*x2 = CoordT(0);
|
||||
*y2 = CoordT(0);
|
||||
|
||||
for(i = 0; i < num; i++)
|
||||
{
|
||||
vs.rewind(gi[start + i]);
|
||||
unsigned cmd;
|
||||
while(!is_stop(cmd = vs.vertex(&x, &y)))
|
||||
{
|
||||
if(is_vertex(cmd))
|
||||
{
|
||||
if(first)
|
||||
{
|
||||
*x1 = CoordT(x);
|
||||
*y1 = CoordT(y);
|
||||
*x2 = CoordT(x);
|
||||
*y2 = CoordT(y);
|
||||
first = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(CoordT(x) < *x1) *x1 = CoordT(x);
|
||||
if(CoordT(y) < *y1) *y1 = CoordT(y);
|
||||
if(CoordT(x) > *x2) *x2 = CoordT(x);
|
||||
if(CoordT(y) > *y2) *y2 = CoordT(y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return *x1 <= *x2 && *y1 <= *y2;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------bounding_rect_single
|
||||
template<class VertexSource, class CoordT>
|
||||
bool bounding_rect_single(VertexSource& vs, unsigned path_id,
|
||||
CoordT* x1, CoordT* y1, CoordT* x2, CoordT* y2)
|
||||
{
|
||||
double x;
|
||||
double y;
|
||||
bool first = true;
|
||||
|
||||
*x1 = CoordT(1);
|
||||
*y1 = CoordT(1);
|
||||
*x2 = CoordT(0);
|
||||
*y2 = CoordT(0);
|
||||
|
||||
vs.rewind(path_id);
|
||||
unsigned cmd;
|
||||
while(!is_stop(cmd = vs.vertex(&x, &y)))
|
||||
{
|
||||
if(is_vertex(cmd))
|
||||
{
|
||||
if(first)
|
||||
{
|
||||
*x1 = CoordT(x);
|
||||
*y1 = CoordT(y);
|
||||
*x2 = CoordT(x);
|
||||
*y2 = CoordT(y);
|
||||
first = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(CoordT(x) < *x1) *x1 = CoordT(x);
|
||||
if(CoordT(y) < *y1) *y1 = CoordT(y);
|
||||
if(CoordT(x) > *x2) *x2 = CoordT(x);
|
||||
if(CoordT(y) > *y2) *y2 = CoordT(y);
|
||||
}
|
||||
}
|
||||
}
|
||||
return *x1 <= *x2 && *y1 <= *y2;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
76
dep/agg/include/agg_bspline.h
Normal file
76
dep/agg/include/agg_bspline.h
Normal file
@@ -0,0 +1,76 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.4
|
||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all copies.
|
||||
// This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// class bspline
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_BSPLINE_INCLUDED
|
||||
#define AGG_BSPLINE_INCLUDED
|
||||
|
||||
#include "agg_array.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//----------------------------------------------------------------bspline
|
||||
// A very simple class of Bi-cubic Spline interpolation.
|
||||
// First call init(num, x[], y[]) where num - number of source points,
|
||||
// x, y - arrays of X and Y values respectively. Here Y must be a function
|
||||
// of X. It means that all the X-coordinates must be arranged in the ascending
|
||||
// order.
|
||||
// Then call get(x) that calculates a value Y for the respective X.
|
||||
// The class supports extrapolation, i.e. you can call get(x) where x is
|
||||
// outside the given with init() X-range. Extrapolation is a simple linear
|
||||
// function.
|
||||
//
|
||||
// See Implementation agg_bspline.cpp
|
||||
//------------------------------------------------------------------------
|
||||
class bspline
|
||||
{
|
||||
public:
|
||||
bspline();
|
||||
bspline(int num);
|
||||
bspline(int num, const double* x, const double* y);
|
||||
|
||||
void init(int num);
|
||||
void add_point(double x, double y);
|
||||
void prepare();
|
||||
|
||||
void init(int num, const double* x, const double* y);
|
||||
|
||||
double get(double x) const;
|
||||
double get_stateful(double x) const;
|
||||
|
||||
private:
|
||||
bspline(const bspline&);
|
||||
const bspline& operator = (const bspline&);
|
||||
|
||||
static void bsearch(int n, const double *x, double x0, int *i);
|
||||
double extrapolation_left(double x) const;
|
||||
double extrapolation_right(double x) const;
|
||||
double interpolation(double x, int i) const;
|
||||
|
||||
int m_max;
|
||||
int m_num;
|
||||
double* m_x;
|
||||
double* m_y;
|
||||
pod_array<double> m_am;
|
||||
mutable int m_last_idx;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
333
dep/agg/include/agg_clip_liang_barsky.h
Normal file
333
dep/agg/include/agg_clip_liang_barsky.h
Normal file
@@ -0,0 +1,333 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.4
|
||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all copies.
|
||||
// This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Liang-Barsky clipping
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
#ifndef AGG_CLIP_LIANG_BARSKY_INCLUDED
|
||||
#define AGG_CLIP_LIANG_BARSKY_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
enum clipping_flags_e
|
||||
{
|
||||
clipping_flags_x1_clipped = 4,
|
||||
clipping_flags_x2_clipped = 1,
|
||||
clipping_flags_y1_clipped = 8,
|
||||
clipping_flags_y2_clipped = 2,
|
||||
clipping_flags_x_clipped = clipping_flags_x1_clipped | clipping_flags_x2_clipped,
|
||||
clipping_flags_y_clipped = clipping_flags_y1_clipped | clipping_flags_y2_clipped
|
||||
};
|
||||
|
||||
//----------------------------------------------------------clipping_flags
|
||||
// Determine the clipping code of the vertex according to the
|
||||
// Cyrus-Beck line clipping algorithm
|
||||
//
|
||||
// | |
|
||||
// 0110 | 0010 | 0011
|
||||
// | |
|
||||
// -------+--------+-------- clip_box.y2
|
||||
// | |
|
||||
// 0100 | 0000 | 0001
|
||||
// | |
|
||||
// -------+--------+-------- clip_box.y1
|
||||
// | |
|
||||
// 1100 | 1000 | 1001
|
||||
// | |
|
||||
// clip_box.x1 clip_box.x2
|
||||
//
|
||||
//
|
||||
template<class T>
|
||||
inline unsigned clipping_flags(T x, T y, const rect_base<T>& clip_box)
|
||||
{
|
||||
return (x > clip_box.x2) |
|
||||
((y > clip_box.y2) << 1) |
|
||||
((x < clip_box.x1) << 2) |
|
||||
((y < clip_box.y1) << 3);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------clipping_flags_x
|
||||
template<class T>
|
||||
inline unsigned clipping_flags_x(T x, const rect_base<T>& clip_box)
|
||||
{
|
||||
return (x > clip_box.x2) | ((x < clip_box.x1) << 2);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------clipping_flags_y
|
||||
template<class T>
|
||||
inline unsigned clipping_flags_y(T y, const rect_base<T>& clip_box)
|
||||
{
|
||||
return ((y > clip_box.y2) << 1) | ((y < clip_box.y1) << 3);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------clip_liang_barsky
|
||||
template<class T>
|
||||
inline unsigned clip_liang_barsky(T x1, T y1, T x2, T y2,
|
||||
const rect_base<T>& clip_box,
|
||||
T* x, T* y)
|
||||
{
|
||||
const double nearzero = 1e-30;
|
||||
|
||||
double deltax = x2 - x1;
|
||||
double deltay = y2 - y1;
|
||||
double xin;
|
||||
double xout;
|
||||
double yin;
|
||||
double yout;
|
||||
double tinx;
|
||||
double tiny;
|
||||
double toutx;
|
||||
double touty;
|
||||
double tin1;
|
||||
double tin2;
|
||||
double tout1;
|
||||
unsigned np = 0;
|
||||
|
||||
if(deltax == 0.0)
|
||||
{
|
||||
// bump off of the vertical
|
||||
deltax = (x1 > clip_box.x1) ? -nearzero : nearzero;
|
||||
}
|
||||
|
||||
if(deltay == 0.0)
|
||||
{
|
||||
// bump off of the horizontal
|
||||
deltay = (y1 > clip_box.y1) ? -nearzero : nearzero;
|
||||
}
|
||||
|
||||
if(deltax > 0.0)
|
||||
{
|
||||
// points to right
|
||||
xin = clip_box.x1;
|
||||
xout = clip_box.x2;
|
||||
}
|
||||
else
|
||||
{
|
||||
xin = clip_box.x2;
|
||||
xout = clip_box.x1;
|
||||
}
|
||||
|
||||
if(deltay > 0.0)
|
||||
{
|
||||
// points up
|
||||
yin = clip_box.y1;
|
||||
yout = clip_box.y2;
|
||||
}
|
||||
else
|
||||
{
|
||||
yin = clip_box.y2;
|
||||
yout = clip_box.y1;
|
||||
}
|
||||
|
||||
tinx = (xin - x1) / deltax;
|
||||
tiny = (yin - y1) / deltay;
|
||||
|
||||
if (tinx < tiny)
|
||||
{
|
||||
// hits x first
|
||||
tin1 = tinx;
|
||||
tin2 = tiny;
|
||||
}
|
||||
else
|
||||
{
|
||||
// hits y first
|
||||
tin1 = tiny;
|
||||
tin2 = tinx;
|
||||
}
|
||||
|
||||
if(tin1 <= 1.0)
|
||||
{
|
||||
if(0.0 < tin1)
|
||||
{
|
||||
*x++ = (T)xin;
|
||||
*y++ = (T)yin;
|
||||
++np;
|
||||
}
|
||||
|
||||
if(tin2 <= 1.0)
|
||||
{
|
||||
toutx = (xout - x1) / deltax;
|
||||
touty = (yout - y1) / deltay;
|
||||
|
||||
tout1 = (toutx < touty) ? toutx : touty;
|
||||
|
||||
if(tin2 > 0.0 || tout1 > 0.0)
|
||||
{
|
||||
if(tin2 <= tout1)
|
||||
{
|
||||
if(tin2 > 0.0)
|
||||
{
|
||||
if(tinx > tiny)
|
||||
{
|
||||
*x++ = (T)xin;
|
||||
*y++ = (T)(y1 + tinx * deltay);
|
||||
}
|
||||
else
|
||||
{
|
||||
*x++ = (T)(x1 + tiny * deltax);
|
||||
*y++ = (T)yin;
|
||||
}
|
||||
++np;
|
||||
}
|
||||
|
||||
if(tout1 < 1.0)
|
||||
{
|
||||
if(toutx < touty)
|
||||
{
|
||||
*x++ = (T)xout;
|
||||
*y++ = (T)(y1 + toutx * deltay);
|
||||
}
|
||||
else
|
||||
{
|
||||
*x++ = (T)(x1 + touty * deltax);
|
||||
*y++ = (T)yout;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*x++ = x2;
|
||||
*y++ = y2;
|
||||
}
|
||||
++np;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(tinx > tiny)
|
||||
{
|
||||
*x++ = (T)xin;
|
||||
*y++ = (T)yout;
|
||||
}
|
||||
else
|
||||
{
|
||||
*x++ = (T)xout;
|
||||
*y++ = (T)yin;
|
||||
}
|
||||
++np;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return np;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
template<class T>
|
||||
bool clip_move_point(T x1, T y1, T x2, T y2,
|
||||
const rect_base<T>& clip_box,
|
||||
T* x, T* y, unsigned flags)
|
||||
{
|
||||
T bound;
|
||||
|
||||
if(flags & clipping_flags_x_clipped)
|
||||
{
|
||||
if(x1 == x2)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bound = (flags & clipping_flags_x1_clipped) ? clip_box.x1 : clip_box.x2;
|
||||
*y = (T)(double(bound - x1) * (y2 - y1) / (x2 - x1) + y1);
|
||||
*x = bound;
|
||||
}
|
||||
|
||||
flags = clipping_flags_y(*y, clip_box);
|
||||
if(flags & clipping_flags_y_clipped)
|
||||
{
|
||||
if(y1 == y2)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bound = (flags & clipping_flags_y1_clipped) ? clip_box.y1 : clip_box.y2;
|
||||
*x = (T)(double(bound - y1) * (x2 - x1) / (y2 - y1) + x1);
|
||||
*y = bound;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------clip_line_segment
|
||||
// Returns: ret >= 4 - Fully clipped
|
||||
// (ret & 1) != 0 - First point has been moved
|
||||
// (ret & 2) != 0 - Second point has been moved
|
||||
//
|
||||
template<class T>
|
||||
unsigned clip_line_segment(T* x1, T* y1, T* x2, T* y2,
|
||||
const rect_base<T>& clip_box)
|
||||
{
|
||||
unsigned f1 = clipping_flags(*x1, *y1, clip_box);
|
||||
unsigned f2 = clipping_flags(*x2, *y2, clip_box);
|
||||
unsigned ret = 0;
|
||||
|
||||
if((f2 | f1) == 0)
|
||||
{
|
||||
// Fully visible
|
||||
return 0;
|
||||
}
|
||||
|
||||
if((f1 & clipping_flags_x_clipped) != 0 &&
|
||||
(f1 & clipping_flags_x_clipped) == (f2 & clipping_flags_x_clipped))
|
||||
{
|
||||
// Fully clipped
|
||||
return 4;
|
||||
}
|
||||
|
||||
if((f1 & clipping_flags_y_clipped) != 0 &&
|
||||
(f1 & clipping_flags_y_clipped) == (f2 & clipping_flags_y_clipped))
|
||||
{
|
||||
// Fully clipped
|
||||
return 4;
|
||||
}
|
||||
|
||||
T tx1 = *x1;
|
||||
T ty1 = *y1;
|
||||
T tx2 = *x2;
|
||||
T ty2 = *y2;
|
||||
if(f1)
|
||||
{
|
||||
if(!clip_move_point(tx1, ty1, tx2, ty2, clip_box, x1, y1, f1))
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
if(*x1 == *x2 && *y1 == *y2)
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
ret |= 1;
|
||||
}
|
||||
if(f2)
|
||||
{
|
||||
if(!clip_move_point(tx1, ty1, tx2, ty2, clip_box, x2, y2, f2))
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
if(*x1 == *x2 && *y1 == *y2)
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
ret |= 2;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
1047
dep/agg/include/agg_color_gray.h
Normal file
1047
dep/agg/include/agg_color_gray.h
Normal file
File diff suppressed because it is too large
Load Diff
1380
dep/agg/include/agg_color_rgba.h
Normal file
1380
dep/agg/include/agg_color_rgba.h
Normal file
File diff suppressed because it is too large
Load Diff
44
dep/agg/include/agg_config.h
Normal file
44
dep/agg/include/agg_config.h
Normal file
@@ -0,0 +1,44 @@
|
||||
#ifndef AGG_CONFIG_INCLUDED
|
||||
#define AGG_CONFIG_INCLUDED
|
||||
|
||||
// This file can be used to redefine certain data types.
|
||||
|
||||
//---------------------------------------
|
||||
// 1. Default basic types such as:
|
||||
//
|
||||
// AGG_INT8
|
||||
// AGG_INT8U
|
||||
// AGG_INT16
|
||||
// AGG_INT16U
|
||||
// AGG_INT32
|
||||
// AGG_INT32U
|
||||
// AGG_INT64
|
||||
// AGG_INT64U
|
||||
//
|
||||
// Just replace this file with new defines if necessary.
|
||||
// For example, if your compiler doesn't have a 64 bit integer type
|
||||
// you can still use AGG if you define the follows:
|
||||
//
|
||||
// #define AGG_INT64 int
|
||||
// #define AGG_INT64U unsigned
|
||||
//
|
||||
// It will result in overflow in 16 bit-per-component image/pattern resampling
|
||||
// but it won't result any crash and the rest of the library will remain
|
||||
// fully functional.
|
||||
|
||||
|
||||
//---------------------------------------
|
||||
// 2. Default rendering_buffer type. Can be:
|
||||
//
|
||||
// Provides faster access for massive pixel operations,
|
||||
// such as blur, image filtering:
|
||||
// #define AGG_RENDERING_BUFFER row_ptr_cache<int8u>
|
||||
//
|
||||
// Provides cheaper creation and destruction (no mem allocs):
|
||||
// #define AGG_RENDERING_BUFFER row_accessor<int8u>
|
||||
//
|
||||
// You can still use both of them simultaneously in your applications
|
||||
// This #define is used only for default rendering_buffer type,
|
||||
// in short hand typedefs like pixfmt_rgba32.
|
||||
|
||||
#endif
|
||||
157
dep/agg/include/agg_conv_adaptor_vcgen.h
Normal file
157
dep/agg/include/agg_conv_adaptor_vcgen.h
Normal file
@@ -0,0 +1,157 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.4
|
||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all copies.
|
||||
// This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_CONV_ADAPTOR_VCGEN_INCLUDED
|
||||
#define AGG_CONV_ADAPTOR_VCGEN_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//------------------------------------------------------------null_markers
|
||||
struct null_markers
|
||||
{
|
||||
void remove_all() {}
|
||||
void add_vertex(double, double, unsigned) {}
|
||||
void prepare_src() {}
|
||||
|
||||
void rewind(unsigned) {}
|
||||
unsigned vertex(double*, double*) { return path_cmd_stop; }
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------------------conv_adaptor_vcgen
|
||||
template<class VertexSource,
|
||||
class Generator,
|
||||
class Markers=null_markers> class conv_adaptor_vcgen
|
||||
{
|
||||
enum status
|
||||
{
|
||||
initial,
|
||||
accumulate,
|
||||
generate
|
||||
};
|
||||
|
||||
public:
|
||||
explicit conv_adaptor_vcgen(VertexSource& source) :
|
||||
m_source(&source),
|
||||
m_status(initial)
|
||||
{}
|
||||
void attach(VertexSource& source) { m_source = &source; }
|
||||
|
||||
Generator& generator() { return m_generator; }
|
||||
const Generator& generator() const { return m_generator; }
|
||||
|
||||
Markers& markers() { return m_markers; }
|
||||
const Markers& markers() const { return m_markers; }
|
||||
|
||||
void rewind(unsigned path_id)
|
||||
{
|
||||
m_source->rewind(path_id);
|
||||
m_status = initial;
|
||||
}
|
||||
|
||||
unsigned vertex(double* x, double* y);
|
||||
|
||||
private:
|
||||
// Prohibit copying
|
||||
conv_adaptor_vcgen(const conv_adaptor_vcgen<VertexSource, Generator, Markers>&);
|
||||
const conv_adaptor_vcgen<VertexSource, Generator, Markers>&
|
||||
operator = (const conv_adaptor_vcgen<VertexSource, Generator, Markers>&);
|
||||
|
||||
VertexSource* m_source;
|
||||
Generator m_generator;
|
||||
Markers m_markers;
|
||||
status m_status;
|
||||
unsigned m_last_cmd;
|
||||
double m_start_x;
|
||||
double m_start_y;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VertexSource, class Generator, class Markers>
|
||||
unsigned conv_adaptor_vcgen<VertexSource, Generator, Markers>::vertex(double* x, double* y)
|
||||
{
|
||||
unsigned cmd = path_cmd_stop;
|
||||
bool done = false;
|
||||
while(!done)
|
||||
{
|
||||
switch(m_status)
|
||||
{
|
||||
case initial:
|
||||
m_markers.remove_all();
|
||||
m_last_cmd = m_source->vertex(&m_start_x, &m_start_y);
|
||||
m_status = accumulate;
|
||||
|
||||
case accumulate:
|
||||
if(is_stop(m_last_cmd)) return path_cmd_stop;
|
||||
|
||||
m_generator.remove_all();
|
||||
m_generator.add_vertex(m_start_x, m_start_y, path_cmd_move_to);
|
||||
m_markers.add_vertex(m_start_x, m_start_y, path_cmd_move_to);
|
||||
|
||||
for(;;)
|
||||
{
|
||||
cmd = m_source->vertex(x, y);
|
||||
if(is_vertex(cmd))
|
||||
{
|
||||
m_last_cmd = cmd;
|
||||
if(is_move_to(cmd))
|
||||
{
|
||||
m_start_x = *x;
|
||||
m_start_y = *y;
|
||||
break;
|
||||
}
|
||||
m_generator.add_vertex(*x, *y, cmd);
|
||||
m_markers.add_vertex(*x, *y, path_cmd_line_to);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(is_stop(cmd))
|
||||
{
|
||||
m_last_cmd = path_cmd_stop;
|
||||
break;
|
||||
}
|
||||
if(is_end_poly(cmd))
|
||||
{
|
||||
m_generator.add_vertex(*x, *y, cmd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_generator.rewind(0);
|
||||
m_status = generate;
|
||||
|
||||
case generate:
|
||||
cmd = m_generator.vertex(x, y);
|
||||
if(is_stop(cmd))
|
||||
{
|
||||
m_status = accumulate;
|
||||
break;
|
||||
}
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return cmd;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
159
dep/agg/include/agg_conv_adaptor_vpgen.h
Normal file
159
dep/agg/include/agg_conv_adaptor_vpgen.h
Normal file
@@ -0,0 +1,159 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.4
|
||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all copies.
|
||||
// This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_CONV_ADAPTOR_VPGEN_INCLUDED
|
||||
#define AGG_CONV_ADAPTOR_VPGEN_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//======================================================conv_adaptor_vpgen
|
||||
template<class VertexSource, class VPGen> class conv_adaptor_vpgen
|
||||
{
|
||||
public:
|
||||
explicit conv_adaptor_vpgen(VertexSource& source) : m_source(&source) {}
|
||||
void attach(VertexSource& source) { m_source = &source; }
|
||||
|
||||
VPGen& vpgen() { return m_vpgen; }
|
||||
const VPGen& vpgen() const { return m_vpgen; }
|
||||
|
||||
void rewind(unsigned path_id);
|
||||
unsigned vertex(double* x, double* y);
|
||||
|
||||
private:
|
||||
conv_adaptor_vpgen(const conv_adaptor_vpgen<VertexSource, VPGen>&);
|
||||
const conv_adaptor_vpgen<VertexSource, VPGen>&
|
||||
operator = (const conv_adaptor_vpgen<VertexSource, VPGen>&);
|
||||
|
||||
VertexSource* m_source;
|
||||
VPGen m_vpgen;
|
||||
double m_start_x;
|
||||
double m_start_y;
|
||||
unsigned m_poly_flags;
|
||||
int m_vertices;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VertexSource, class VPGen>
|
||||
void conv_adaptor_vpgen<VertexSource, VPGen>::rewind(unsigned path_id)
|
||||
{
|
||||
m_source->rewind(path_id);
|
||||
m_vpgen.reset();
|
||||
m_start_x = 0;
|
||||
m_start_y = 0;
|
||||
m_poly_flags = 0;
|
||||
m_vertices = 0;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VertexSource, class VPGen>
|
||||
unsigned conv_adaptor_vpgen<VertexSource, VPGen>::vertex(double* x, double* y)
|
||||
{
|
||||
unsigned cmd = path_cmd_stop;
|
||||
for(;;)
|
||||
{
|
||||
cmd = m_vpgen.vertex(x, y);
|
||||
if(!is_stop(cmd)) break;
|
||||
|
||||
if(m_poly_flags && !m_vpgen.auto_unclose())
|
||||
{
|
||||
*x = 0.0;
|
||||
*y = 0.0;
|
||||
cmd = m_poly_flags;
|
||||
m_poly_flags = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if(m_vertices < 0)
|
||||
{
|
||||
if(m_vertices < -1)
|
||||
{
|
||||
m_vertices = 0;
|
||||
return path_cmd_stop;
|
||||
}
|
||||
m_vpgen.move_to(m_start_x, m_start_y);
|
||||
m_vertices = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
double tx, ty;
|
||||
cmd = m_source->vertex(&tx, &ty);
|
||||
if(is_vertex(cmd))
|
||||
{
|
||||
if(is_move_to(cmd))
|
||||
{
|
||||
if(m_vpgen.auto_close() && m_vertices > 2)
|
||||
{
|
||||
m_vpgen.line_to(m_start_x, m_start_y);
|
||||
m_poly_flags = path_cmd_end_poly | path_flags_close;
|
||||
m_start_x = tx;
|
||||
m_start_y = ty;
|
||||
m_vertices = -1;
|
||||
continue;
|
||||
}
|
||||
m_vpgen.move_to(tx, ty);
|
||||
m_start_x = tx;
|
||||
m_start_y = ty;
|
||||
m_vertices = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_vpgen.line_to(tx, ty);
|
||||
++m_vertices;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(is_end_poly(cmd))
|
||||
{
|
||||
m_poly_flags = cmd;
|
||||
if(is_closed(cmd) || m_vpgen.auto_close())
|
||||
{
|
||||
if(m_vpgen.auto_close()) m_poly_flags |= path_flags_close;
|
||||
if(m_vertices > 2)
|
||||
{
|
||||
m_vpgen.line_to(m_start_x, m_start_y);
|
||||
}
|
||||
m_vertices = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// path_cmd_stop
|
||||
if(m_vpgen.auto_close() && m_vertices > 2)
|
||||
{
|
||||
m_vpgen.line_to(m_start_x, m_start_y);
|
||||
m_poly_flags = path_cmd_end_poly | path_flags_close;
|
||||
m_vertices = -2;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return cmd;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
48
dep/agg/include/agg_conv_bspline.h
Normal file
48
dep/agg/include/agg_conv_bspline.h
Normal file
@@ -0,0 +1,48 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.4
|
||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all copies.
|
||||
// This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
#ifndef AGG_CONV_BSPLINE_INCLUDED
|
||||
#define AGG_CONV_BSPLINE_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_vcgen_bspline.h"
|
||||
#include "agg_conv_adaptor_vcgen.h"
|
||||
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//---------------------------------------------------------conv_bspline
|
||||
template<class VertexSource>
|
||||
struct conv_bspline : public conv_adaptor_vcgen<VertexSource, vcgen_bspline>
|
||||
{
|
||||
typedef conv_adaptor_vcgen<VertexSource, vcgen_bspline> base_type;
|
||||
|
||||
conv_bspline(VertexSource& vs) :
|
||||
conv_adaptor_vcgen<VertexSource, vcgen_bspline>(vs) {}
|
||||
|
||||
void interpolation_step(double v) { base_type::generator().interpolation_step(v); }
|
||||
double interpolation_step() const { return base_type::generator().interpolation_step(); }
|
||||
|
||||
private:
|
||||
conv_bspline(const conv_bspline<VertexSource>&);
|
||||
const conv_bspline<VertexSource>&
|
||||
operator = (const conv_bspline<VertexSource>&);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
63
dep/agg/include/agg_conv_clip_polygon.h
Normal file
63
dep/agg/include/agg_conv_clip_polygon.h
Normal file
@@ -0,0 +1,63 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.4
|
||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all copies.
|
||||
// This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Polygon clipping converter
|
||||
// There an optimized Liang-Basky algorithm is used.
|
||||
// The algorithm doesn't optimize the degenerate edges, i.e. it will never
|
||||
// break a closed polygon into two or more ones, instead, there will be
|
||||
// degenerate edges coinciding with the respective clipping boundaries.
|
||||
// This is a sub-optimal solution, because that optimization would require
|
||||
// extra, rather expensive math while the rasterizer tolerates it quite well,
|
||||
// without any considerable overhead.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
#ifndef AGG_CONV_CLIP_POLYGON_INCLUDED
|
||||
#define AGG_CONV_CLIP_POLYGON_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_conv_adaptor_vpgen.h"
|
||||
#include "agg_vpgen_clip_polygon.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//=======================================================conv_clip_polygon
|
||||
template<class VertexSource>
|
||||
struct conv_clip_polygon : public conv_adaptor_vpgen<VertexSource, vpgen_clip_polygon>
|
||||
{
|
||||
typedef conv_adaptor_vpgen<VertexSource, vpgen_clip_polygon> base_type;
|
||||
|
||||
conv_clip_polygon(VertexSource& vs) :
|
||||
conv_adaptor_vpgen<VertexSource, vpgen_clip_polygon>(vs) {}
|
||||
|
||||
void clip_box(double x1, double y1, double x2, double y2)
|
||||
{
|
||||
base_type::vpgen().clip_box(x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
double x1() const { return base_type::vpgen().x1(); }
|
||||
double y1() const { return base_type::vpgen().y1(); }
|
||||
double x2() const { return base_type::vpgen().x2(); }
|
||||
double y2() const { return base_type::vpgen().y2(); }
|
||||
|
||||
private:
|
||||
conv_clip_polygon(const conv_clip_polygon<VertexSource>&);
|
||||
const conv_clip_polygon<VertexSource>&
|
||||
operator = (const conv_clip_polygon<VertexSource>&);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
63
dep/agg/include/agg_conv_clip_polyline.h
Normal file
63
dep/agg/include/agg_conv_clip_polyline.h
Normal file
@@ -0,0 +1,63 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.4
|
||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all copies.
|
||||
// This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// polyline clipping converter
|
||||
// There an optimized Liang-Basky algorithm is used.
|
||||
// The algorithm doesn't optimize the degenerate edges, i.e. it will never
|
||||
// break a closed polyline into two or more ones, instead, there will be
|
||||
// degenerate edges coinciding with the respective clipping boundaries.
|
||||
// This is a sub-optimal solution, because that optimization would require
|
||||
// extra, rather expensive math while the rasterizer tolerates it quite well,
|
||||
// without any considerable overhead.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
#ifndef AGG_CONV_CLIP_polyline_INCLUDED
|
||||
#define AGG_CONV_CLIP_polyline_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
#include "agg_conv_adaptor_vpgen.h"
|
||||
#include "agg_vpgen_clip_polyline.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//=======================================================conv_clip_polyline
|
||||
template<class VertexSource>
|
||||
struct conv_clip_polyline : public conv_adaptor_vpgen<VertexSource, vpgen_clip_polyline>
|
||||
{
|
||||
typedef conv_adaptor_vpgen<VertexSource, vpgen_clip_polyline> base_type;
|
||||
|
||||
conv_clip_polyline(VertexSource& vs) :
|
||||
conv_adaptor_vpgen<VertexSource, vpgen_clip_polyline>(vs) {}
|
||||
|
||||
void clip_box(double x1, double y1, double x2, double y2)
|
||||
{
|
||||
base_type::vpgen().clip_box(x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
double x1() const { return base_type::vpgen().x1(); }
|
||||
double y1() const { return base_type::vpgen().y1(); }
|
||||
double x2() const { return base_type::vpgen().x2(); }
|
||||
double y2() const { return base_type::vpgen().y2(); }
|
||||
|
||||
private:
|
||||
conv_clip_polyline(const conv_clip_polyline<VertexSource>&);
|
||||
const conv_clip_polyline<VertexSource>&
|
||||
operator = (const conv_clip_polyline<VertexSource>&);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
125
dep/agg/include/agg_conv_close_polygon.h
Normal file
125
dep/agg/include/agg_conv_close_polygon.h
Normal file
@@ -0,0 +1,125 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.4
|
||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all copies.
|
||||
// This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_CONV_CLOSE_POLYGON_INCLUDED
|
||||
#define AGG_CONV_CLOSE_POLYGON_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
|
||||
//======================================================conv_close_polygon
|
||||
template<class VertexSource> class conv_close_polygon
|
||||
{
|
||||
public:
|
||||
explicit conv_close_polygon(VertexSource& vs) : m_source(&vs) {}
|
||||
void attach(VertexSource& source) { m_source = &source; }
|
||||
|
||||
void rewind(unsigned path_id);
|
||||
unsigned vertex(double* x, double* y);
|
||||
|
||||
private:
|
||||
conv_close_polygon(const conv_close_polygon<VertexSource>&);
|
||||
const conv_close_polygon<VertexSource>&
|
||||
operator = (const conv_close_polygon<VertexSource>&);
|
||||
|
||||
VertexSource* m_source;
|
||||
unsigned m_cmd[2];
|
||||
double m_x[2];
|
||||
double m_y[2];
|
||||
unsigned m_vertex;
|
||||
bool m_line_to;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VertexSource>
|
||||
void conv_close_polygon<VertexSource>::rewind(unsigned path_id)
|
||||
{
|
||||
m_source->rewind(path_id);
|
||||
m_vertex = 2;
|
||||
m_line_to = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template<class VertexSource>
|
||||
unsigned conv_close_polygon<VertexSource>::vertex(double* x, double* y)
|
||||
{
|
||||
unsigned cmd = path_cmd_stop;
|
||||
for(;;)
|
||||
{
|
||||
if(m_vertex < 2)
|
||||
{
|
||||
*x = m_x[m_vertex];
|
||||
*y = m_y[m_vertex];
|
||||
cmd = m_cmd[m_vertex];
|
||||
++m_vertex;
|
||||
break;
|
||||
}
|
||||
|
||||
cmd = m_source->vertex(x, y);
|
||||
|
||||
if(is_end_poly(cmd))
|
||||
{
|
||||
cmd |= path_flags_close;
|
||||
break;
|
||||
}
|
||||
|
||||
if(is_stop(cmd))
|
||||
{
|
||||
if(m_line_to)
|
||||
{
|
||||
m_cmd[0] = path_cmd_end_poly | path_flags_close;
|
||||
m_cmd[1] = path_cmd_stop;
|
||||
m_vertex = 0;
|
||||
m_line_to = false;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(is_move_to(cmd))
|
||||
{
|
||||
if(m_line_to)
|
||||
{
|
||||
m_x[0] = 0.0;
|
||||
m_y[0] = 0.0;
|
||||
m_cmd[0] = path_cmd_end_poly | path_flags_close;
|
||||
m_x[1] = *x;
|
||||
m_y[1] = *y;
|
||||
m_cmd[1] = cmd;
|
||||
m_vertex = 0;
|
||||
m_line_to = false;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(is_vertex(cmd))
|
||||
{
|
||||
m_line_to = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return cmd;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
73
dep/agg/include/agg_conv_concat.h
Normal file
73
dep/agg/include/agg_conv_concat.h
Normal file
@@ -0,0 +1,73 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.4
|
||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all copies.
|
||||
// This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_CONV_CONCAT_INCLUDED
|
||||
#define AGG_CONV_CONCAT_INCLUDED
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
//=============================================================conv_concat
|
||||
// Concatenation of two paths. Usually used to combine lines or curves
|
||||
// with markers such as arrowheads
|
||||
template<class VS1, class VS2> class conv_concat
|
||||
{
|
||||
public:
|
||||
conv_concat(VS1& source1, VS2& source2) :
|
||||
m_source1(&source1), m_source2(&source2), m_status(2) {}
|
||||
void attach1(VS1& source) { m_source1 = &source; }
|
||||
void attach2(VS2& source) { m_source2 = &source; }
|
||||
|
||||
|
||||
void rewind(unsigned path_id)
|
||||
{
|
||||
m_source1->rewind(path_id);
|
||||
m_source2->rewind(0);
|
||||
m_status = 0;
|
||||
}
|
||||
|
||||
unsigned vertex(double* x, double* y)
|
||||
{
|
||||
unsigned cmd;
|
||||
if(m_status == 0)
|
||||
{
|
||||
cmd = m_source1->vertex(x, y);
|
||||
if(!is_stop(cmd)) return cmd;
|
||||
m_status = 1;
|
||||
}
|
||||
if(m_status == 1)
|
||||
{
|
||||
cmd = m_source2->vertex(x, y);
|
||||
if(!is_stop(cmd)) return cmd;
|
||||
m_status = 2;
|
||||
}
|
||||
return path_cmd_stop;
|
||||
}
|
||||
|
||||
private:
|
||||
conv_concat(const conv_concat<VS1, VS2>&);
|
||||
const conv_concat<VS1, VS2>&
|
||||
operator = (const conv_concat<VS1, VS2>&);
|
||||
|
||||
VS1* m_source1;
|
||||
VS2* m_source2;
|
||||
int m_status;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user