Compare commits
22 Commits
loadExampl
...
user-im-n-
Author | SHA1 | Date | |
---|---|---|---|
964d34f73a | |||
f2fe410cc1 | |||
8b3d2d525b | |||
a92da271d1 | |||
c4a1884c6d | |||
1d7169ddb2 | |||
8867374f85 | |||
b3478d7eb3 | |||
f4ad57b544 | |||
51d8ccf148 | |||
87ec19157b | |||
5664e0483b | |||
95985eb92a | |||
c4a54ee2e4 | |||
8d0aded26f | |||
ca60d8bae8 | |||
a8195a3fba | |||
88f84a9c25 | |||
6bbed4c655 | |||
49863a0079 | |||
9b789a1378 | |||
1b7a502cd4 |
7
.gitignore
vendored
7
.gitignore
vendored
@ -1,3 +1,8 @@
|
||||
desktop.ini
|
||||
|
||||
elm-stuff/*
|
||||
elm-stuff/*
|
||||
out/js/elm.js
|
||||
*.zip
|
||||
|
||||
*.sublime*
|
||||
|
||||
|
25
build.sh
Normal file
25
build.sh
Normal file
@ -0,0 +1,25 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
IFS=$'\n\t'
|
||||
|
||||
echo "Building..."
|
||||
|
||||
# Create folders
|
||||
mkdir -p out/css
|
||||
mkdir -p out/js
|
||||
|
||||
|
||||
# JS + TS
|
||||
#cp src/js/*.js out/js/
|
||||
# tsc --lib es2015 --lib dom --outDir out/js src/js/*.ts
|
||||
|
||||
|
||||
# Compile Elm
|
||||
elm make src/Main.elm --output out/js/elm.js --optimize
|
||||
|
||||
# CSS
|
||||
#cp src/css/*.css out/css/
|
||||
|
||||
# cp out/main.js js/main.julius
|
||||
|
||||
echo "Build complete"
|
3
elm-tooling.json
Normal file
3
elm-tooling.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"entrypoints": ["./src/Main.elm"]
|
||||
}
|
2
elm.json
2
elm.json
@ -8,13 +8,13 @@
|
||||
"direct": {
|
||||
"elm/browser": "1.0.2",
|
||||
"elm/core": "1.0.5",
|
||||
"elm/file": "1.0.5",
|
||||
"elm/html": "1.0.0",
|
||||
"elm/http": "2.0.0",
|
||||
"elm/json": "1.1.3"
|
||||
},
|
||||
"indirect": {
|
||||
"elm/bytes": "1.0.8",
|
||||
"elm/file": "1.0.5",
|
||||
"elm/time": "1.0.0",
|
||||
"elm/url": "1.0.0",
|
||||
"elm/virtual-dom": "1.0.2"
|
||||
|
@ -51,6 +51,7 @@
|
||||
--color-controls-button-text: var(--color-white);
|
||||
--color-controls-button-border: var(--color-white);
|
||||
--color-controls-button-text-hover: var(--color-white-light1);
|
||||
--color-controls-scroller-label-text: var(--color-black);
|
||||
|
||||
--color-header: var(--color-grey);
|
||||
--color-header-text: var(--color-white);
|
||||
@ -77,6 +78,7 @@
|
||||
--color-table-ram-select: transparent;
|
||||
--color-table-ram-select-text: inherit;
|
||||
--color-table-ram-select-border: var(--color-grey-light2);
|
||||
--color-table-ram-button-border: var(--color-controls-button-border);
|
||||
|
||||
--color-table-cu-head: var(--color-cu-dark1);
|
||||
--color-table-cu-head-text: var(--color-white);
|
||||
@ -85,6 +87,7 @@
|
||||
--color-table-cu-select: transparent;
|
||||
--color-table-cu-select-text: inherit;
|
||||
--color-table-cu-select-border: var(--color-grey-light2);
|
||||
--color-table-cu-button-border: var(--color-controls-button-border);
|
||||
|
||||
--color-arrow: var(--color-arrow-main);
|
||||
--color-arrow-text: var(--color-white);
|
||||
@ -97,6 +100,11 @@
|
||||
|
||||
--color-code: var(--color-black-light1);
|
||||
--color-code-text: var(--color-white);
|
||||
|
||||
--color-dragdrop: var(--color-code);
|
||||
--color-dragdrop-text: var(--color-white);
|
||||
--color-dragdrop-processing: var(--color-cu-main);
|
||||
--color-dragdrop-processing-text: var(--color-white);
|
||||
}
|
||||
|
||||
|
||||
|
@ -50,6 +50,7 @@
|
||||
--color-controls-button-text: var(--color-black);
|
||||
--color-controls-button-border: var(--color-black);
|
||||
--color-controls-button-text-hover: var(--color-black-light1);
|
||||
--color-controls-scroller-label-text: var(--color-white);
|
||||
|
||||
--color-header: var(--color-grey);
|
||||
--color-header-text: var(--color-white);
|
||||
@ -76,6 +77,7 @@
|
||||
--color-table-ram-select: transparent;
|
||||
--color-table-ram-select-text: inherit;
|
||||
--color-table-ram-select-border: var(--color-grey-light2);
|
||||
--color-table-ram-button-border: var(--color-controls-button-border);
|
||||
|
||||
--color-table-cu-head: var(--color-cu-dark1);
|
||||
--color-table-cu-head-text: var(--color-white);
|
||||
@ -84,6 +86,7 @@
|
||||
--color-table-cu-select: transparent;
|
||||
--color-table-cu-select-text: inherit;
|
||||
--color-table-cu-select-border: var(--color-grey-light2);
|
||||
--color-table-cu-button-border: var(--color-controls-button-border);
|
||||
|
||||
--color-arrow: var(--color-arrow-main);
|
||||
--color-arrow-text: var(--color-white);
|
||||
@ -96,6 +99,11 @@
|
||||
|
||||
--color-code: var(--color-white-light2);
|
||||
--color-code-text: var(--color-black);
|
||||
|
||||
--color-dragdrop: var(--color-code);
|
||||
--color-dragdrop-text: var(--color-black);
|
||||
--color-dragdrop-processing: var(--color-cu-light1);
|
||||
--color-dragdrop-processing-text: var(--color-black);
|
||||
}
|
||||
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
width: 100vw;
|
||||
height: min-content;
|
||||
|
||||
color: black;
|
||||
background-color: white;
|
||||
border-top: 1px solid black;
|
||||
|
||||
@ -20,6 +21,9 @@
|
||||
padding: .5rem 1rem;
|
||||
margin: 0;
|
||||
line-height: 1em;
|
||||
|
||||
color: black;
|
||||
border-color: black;
|
||||
}
|
||||
|
||||
.cookie-banner * {
|
||||
@ -33,4 +37,17 @@
|
||||
|
||||
.cookie-banner > :last-child {
|
||||
margin-right: 0 !important;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark){
|
||||
.cookie-banner {
|
||||
background-color: black;
|
||||
border-color: white;
|
||||
color: white;
|
||||
}
|
||||
.cookie-banner button{
|
||||
color: white;
|
||||
border-color: white;
|
||||
}
|
||||
|
||||
}
|
310
out/css/loader.css
Normal file
310
out/css/loader.css
Normal file
@ -0,0 +1,310 @@
|
||||
/* Variables */
|
||||
* {
|
||||
--loaderDivCol: var(--color-dragdrop-processing-text);
|
||||
|
||||
--circR: 1rem;
|
||||
--circD: 2rem;
|
||||
--circ6D: 12rem;
|
||||
|
||||
--timing: ease-in-out;
|
||||
--fullCycle: 5s;
|
||||
}
|
||||
|
||||
.loader.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.loader {
|
||||
position: relative;
|
||||
|
||||
box-sizing: border-box;
|
||||
height: var(--circD);
|
||||
width: var(--circ6D);
|
||||
|
||||
margin: calc(var(--circD) * 3) var(--circD);
|
||||
padding: var(--circR) 0;
|
||||
}
|
||||
|
||||
.loader > * {
|
||||
position: absolute;
|
||||
box-sizing: border-box;
|
||||
height: 0;
|
||||
width: calc(2 * var(--circD));
|
||||
opacity: 0;
|
||||
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
--keyframe-sequence: "loading0";
|
||||
--delay: 0;
|
||||
--animation: var(--keyframe-sequence) var(--fullCycle) var(--timing) calc(0s - var(--fullCycle) * (1 - (var(--delay)) / 8) ) infinite;
|
||||
|
||||
-webkit-animation: var(--animation);
|
||||
-moz-animation: var(--animation);
|
||||
-ms-animation: var(--animation);
|
||||
-o-animation: var(--animation);
|
||||
animation: var(--animation);
|
||||
}
|
||||
|
||||
.loader div::before,
|
||||
.loader div::after {
|
||||
content: "";
|
||||
display: block;
|
||||
box-sizing: border-box;
|
||||
width: var(--circD);
|
||||
height: var(--circD);
|
||||
border: 1px solid var(--loaderDivCol);
|
||||
background: var(--loaderDivCol);
|
||||
border-radius: 100%;
|
||||
|
||||
position: absolute;
|
||||
top: calc(0px - var(--circR));
|
||||
}
|
||||
|
||||
.loader div::before {
|
||||
left: calc(0px - var(--circR));
|
||||
}
|
||||
.loader div::after {
|
||||
right: calc(0px - var(--circR));
|
||||
}
|
||||
|
||||
|
||||
@keyframes loading0 {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
opacity: 1;
|
||||
}
|
||||
12.52% {
|
||||
opacity: 1;
|
||||
}
|
||||
12.56% {
|
||||
opacity: 0;
|
||||
}
|
||||
99.7% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes loading2 {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
opacity: 1;
|
||||
}
|
||||
7% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
12.47% {
|
||||
opacity: 1;
|
||||
}
|
||||
12.56% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
24.6% {
|
||||
opacity: 0;
|
||||
}
|
||||
24.97% {
|
||||
opacity: 1;
|
||||
}
|
||||
37.52% {
|
||||
opacity: 1;
|
||||
}
|
||||
37.57% {
|
||||
opacity: 0;
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
99.95% {
|
||||
opacity: 0;
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes loading3 {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
opacity: 1;
|
||||
}
|
||||
7% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
12.47% {
|
||||
opacity: 1;
|
||||
}
|
||||
12.52% {
|
||||
opacity: 1;
|
||||
}
|
||||
12.56% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
37.4% {
|
||||
opacity: 0;
|
||||
}
|
||||
37.47% {
|
||||
opacity: 1;
|
||||
}
|
||||
50.02% {
|
||||
opacity: 1;
|
||||
}
|
||||
50.1% {
|
||||
opacity: 0;
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
99.8% {
|
||||
opacity: 0;
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes loading5 {
|
||||
0% {
|
||||
opacity: 1;
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
7% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
12.47% {
|
||||
opacity: 1;
|
||||
}
|
||||
12.52% {
|
||||
opacity: 1;
|
||||
}
|
||||
12.58% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
62.4% {
|
||||
opacity: 0;
|
||||
}
|
||||
62.47% {
|
||||
opacity: 1;
|
||||
}
|
||||
75.02% {
|
||||
opacity: 1;
|
||||
}
|
||||
75.1% {
|
||||
opacity: 0;
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
99.7% {
|
||||
transform: rotate(0deg);
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes loading6 {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
opacity: 1;
|
||||
}
|
||||
7% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
12.47% {
|
||||
opacity: 1;
|
||||
}
|
||||
12.52% {
|
||||
opacity: 1;
|
||||
}
|
||||
12.57% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
74.85% {
|
||||
opacity: 0;
|
||||
}
|
||||
74.97% {
|
||||
opacity: 1;
|
||||
}
|
||||
87.52% {
|
||||
opacity: 1;
|
||||
}
|
||||
87.6% {
|
||||
opacity: 0;
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
99.8% {
|
||||
opacity: 0;
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.loader :nth-child(1) {
|
||||
width: 66.66%;
|
||||
--keyframe-sequence: "loading5";
|
||||
--delay: 0;
|
||||
}
|
||||
.loader :nth-child(2) {
|
||||
width: 66.66%;
|
||||
margin-left: 0;
|
||||
--keyframe-sequence: "loading2";
|
||||
--delay: 0;
|
||||
}
|
||||
.loader :nth-child(3) {
|
||||
width: 33.33%;
|
||||
margin-left: 33.33%;
|
||||
--keyframe-sequence: "loading2";
|
||||
--delay: 1;
|
||||
}
|
||||
.loader :nth-child(4) {
|
||||
width: 66.66%;
|
||||
margin-left: 33.33%;
|
||||
--keyframe-sequence: "loading6";
|
||||
--delay: 2;
|
||||
}
|
||||
|
||||
.loader :nth-child(5) {
|
||||
width: 100%;
|
||||
--keyframe-sequence: "loading6";
|
||||
--delay: 3;
|
||||
}
|
||||
.loader :nth-child(6) {
|
||||
width: 100%;
|
||||
--keyframe-sequence: "loading3";
|
||||
--delay: 3;
|
||||
}
|
||||
.loader :nth-child(7) {
|
||||
width: 33.33%;
|
||||
--keyframe-sequence: "loading3";
|
||||
--delay: 4;
|
||||
}
|
||||
.loader :nth-child(8) {
|
||||
width: 66.66%;
|
||||
margin-left: 33.33%;
|
||||
--keyframe-sequence: "loading3";
|
||||
--delay: 5;
|
||||
}
|
||||
.loader :nth-child(9) {
|
||||
width: 33.33%;
|
||||
margin-left: 33.33%;
|
||||
--keyframe-sequence: "loading5";
|
||||
--delay: 6;
|
||||
}
|
||||
.loader :nth-child(10) {
|
||||
width: 33.33%;
|
||||
margin-left: 66.66%;
|
||||
--keyframe-sequence: "loading5";
|
||||
--delay: 7;
|
||||
}
|
838
out/css/pc.css
838
out/css/pc.css
File diff suppressed because it is too large
Load Diff
296
out/css/roller.css
Normal file
296
out/css/roller.css
Normal file
@ -0,0 +1,296 @@
|
||||
|
||||
/*
|
||||
Roller
|
||||
*/
|
||||
|
||||
* {
|
||||
--loaderDivCol: #eee;
|
||||
|
||||
--circD: 1rem;
|
||||
--circ6D: 6rem;
|
||||
--circR: 0.5rem;
|
||||
|
||||
--scrollbarBG: #f5f5f5;
|
||||
--thumbBG: #C1DCEA;
|
||||
}
|
||||
|
||||
#elm {
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.roller {
|
||||
margin: 2.5rem 0;
|
||||
}
|
||||
|
||||
@keyframes loading0 {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
opacity: 1;
|
||||
}
|
||||
7% {
|
||||
transform: rotate(0deg);
|
||||
opacity: 1;
|
||||
}
|
||||
12.47% {
|
||||
opacity: 1;
|
||||
}
|
||||
12.52% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes loading2 {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
opacity: 1;
|
||||
}
|
||||
7% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
12.47% {
|
||||
opacity: 1;
|
||||
}
|
||||
12.52% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
24.97% {
|
||||
opacity: 0;
|
||||
}
|
||||
25.02% {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
37.47% {
|
||||
opacity: 1;
|
||||
}
|
||||
37.52% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
99.95% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes loading3 {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
opacity: 1;
|
||||
}
|
||||
7% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
12.47% {
|
||||
opacity: 1;
|
||||
}
|
||||
12.52% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
37.47% {
|
||||
opacity: 0;
|
||||
}
|
||||
37.52% {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
49.97% {
|
||||
opacity: 1;
|
||||
}
|
||||
50.02% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 0;
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes loading5 {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
opacity: 1;
|
||||
}
|
||||
7% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
12.47% {
|
||||
opacity: 1;
|
||||
}
|
||||
12.52% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
62.47% {
|
||||
opacity: 0;
|
||||
}
|
||||
62.52% {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
74.97% {
|
||||
opacity: 1;
|
||||
}
|
||||
75.02% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 0;
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes loading6 {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
opacity: 1;
|
||||
}
|
||||
7% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
12.47% {
|
||||
opacity: 1;
|
||||
}
|
||||
12.52% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
74.97% {
|
||||
opacity: 0;
|
||||
}
|
||||
75.02% {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
87.47% {
|
||||
opacity: 1;
|
||||
}
|
||||
87.52% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 0;
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
}
|
||||
|
||||
.loader {
|
||||
position: relative;
|
||||
height: var(--circD);
|
||||
width: var(--circ6D);
|
||||
padding: var(--circR) 0;
|
||||
box-sizing: border-box;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
|
||||
.loader :nth-child(n) {
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
box-sizing: border-box;
|
||||
width: 0;
|
||||
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.loader div::before,
|
||||
.loader div::after {
|
||||
content: "";
|
||||
display: block;
|
||||
width: var(--circD);
|
||||
height: var(--circD);
|
||||
border: 1px solid var(--loaderDivCol);
|
||||
background: var(--loaderDivCol);
|
||||
border-radius: 100%;
|
||||
|
||||
position: absolute;
|
||||
top: var(--circR);
|
||||
}
|
||||
|
||||
.loader div::before {
|
||||
left: calc(-var(--circR));
|
||||
}
|
||||
.loader div::after {
|
||||
right: calc(-var(--circR));
|
||||
}
|
||||
|
||||
|
||||
.loader :nth-child(1) {
|
||||
width: 66.66%;
|
||||
/*^{animation "loading5" (timeDiv 0)}*/
|
||||
|
||||
--timing: "cubic-bezier(.39,.58,.57,1)";
|
||||
--fullCycle: "4s";
|
||||
--animation: "loading5" var(--fullCycle) var(--timing) calc(-(var(--fullCycle) * 1 / 8 )) infinite;
|
||||
-webkit-animation: var(--animation);
|
||||
-moz-animation: var(--animation);
|
||||
-ms-animation: var(--animation);
|
||||
-o-animation: var(--animation);
|
||||
animation: var(--animation);
|
||||
|
||||
/*- fromInteger fullDiv * (1 - (fromInteger a) / 8 )*/
|
||||
}
|
||||
.loader :nth-child(2) {
|
||||
width: 66.66%;
|
||||
margin-left: 0;
|
||||
/*^{animation "loading2" (timeDiv 0)}*/
|
||||
}
|
||||
.loader :nth-child(3) {
|
||||
width: 33.33%
|
||||
margin-left: 33.33%
|
||||
/*^{animation "loading2" (timeDiv 1)}*/
|
||||
}
|
||||
.loader :nth-child(4) {
|
||||
width: 66.66%
|
||||
margin-left: 33.33%
|
||||
/*^{animation "loading6" (timeDiv 2)}*/
|
||||
}
|
||||
|
||||
|
||||
.loader :nth-child(5) {
|
||||
width: 100%
|
||||
/*^{animation "loading6" (timeDiv 3)} */
|
||||
}
|
||||
.loader :nth-child(6) {
|
||||
width: 100%
|
||||
/*^{animation "loading3" (timeDiv 3)}*/
|
||||
}
|
||||
.loader :nth-child(7) {
|
||||
width: 33.33%
|
||||
/*^{animation "loading3" (timeDiv 4)}*/
|
||||
}
|
||||
.loader :nth-child(8) {
|
||||
width: 66.66%
|
||||
margin-left: 33.33%
|
||||
/*^{animation "loading3" (timeDiv 5)}*/
|
||||
}
|
||||
.loader :nth-child(9) {
|
||||
width: 33.33%
|
||||
margin-left: 33.33%
|
||||
/*^{animation "loading5" (timeDiv 6)}*/
|
||||
}
|
||||
.loader :nth-child(10) {
|
||||
width: 33.33%
|
||||
margin-left: 66.66%
|
||||
/*^{animation "loading5" (timeDiv 7)} */
|
||||
}
|
@ -36,8 +36,96 @@ footer{
|
||||
}
|
||||
|
||||
|
||||
.dragDrop {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100vh;
|
||||
width: 100%;
|
||||
|
||||
background-color: var(--color-dragdrop);
|
||||
color: var(--color-dragdrop-text);
|
||||
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
z-index: 1000;
|
||||
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
|
||||
--transition: all 0.25s ease-in-out 0s;
|
||||
transition: var(--transition);
|
||||
}
|
||||
.dragDrop.hover, .dragDrop.loading {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
.dragDrop.loading {
|
||||
background-color: var(--color-dragdrop-processing);
|
||||
color: var(--color-dragdrop-processing-text);
|
||||
}
|
||||
.dragDrop .loader {
|
||||
display: none;
|
||||
}
|
||||
.dragDrop.loading .loader {
|
||||
display: block;
|
||||
}
|
||||
/*.dragDrop.loading p:first-child::before {
|
||||
content: "⋮";
|
||||
|
||||
display: inline-flex;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
align-content: center;
|
||||
transform: rotate(0);
|
||||
}*/
|
||||
|
||||
.pc .examples-list {
|
||||
border: 1px solid var(--color-controls-button-border);
|
||||
margin: 0;
|
||||
border-radius: 0 4px 4px 4px;
|
||||
}
|
||||
|
||||
.pc .examples-list table td:first-child {
|
||||
padding: 12px 8px 12px 15px;
|
||||
}
|
||||
|
||||
.pc .example-scroller-label {
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
border: 1px solid var(--color-controls-button-border);
|
||||
border-bottom-style: none;
|
||||
color: var(--color-controls-button-text);
|
||||
border-radius: 4px 4px 0 0;
|
||||
padding: 2px 15px;
|
||||
}
|
||||
|
||||
button, .button {
|
||||
/* background-color: whitesmoke; */
|
||||
color: var(--color-controls-button-text);
|
||||
border-color: var(--color-controls-button-border);
|
||||
}
|
||||
button:hover, .button:hover{
|
||||
color: var(--color-controls-button-text-hover);
|
||||
}
|
||||
|
||||
.button-group {
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
.button-group > * {
|
||||
border-radius: 0;
|
||||
}
|
||||
.button-group :first-child {
|
||||
border-radius: 4px 0 0 4px;
|
||||
}
|
||||
.button-group :last-child {
|
||||
border-radius: 0 4px 4px 0;
|
||||
}
|
||||
|
||||
/* HELPERS */
|
||||
.text-center {
|
||||
|
@ -1,17 +1,23 @@
|
||||
{
|
||||
"available":
|
||||
[
|
||||
{
|
||||
"title": "Simple Counter",
|
||||
"version": "0.1",
|
||||
"available":
|
||||
[
|
||||
{
|
||||
"title": "A simple Counter",
|
||||
"version": "0.3",
|
||||
"url": "examples/simple-counter.json",
|
||||
"enabled": 1
|
||||
},
|
||||
{
|
||||
"title": "Add 2 numbers(placeholder)",
|
||||
"version": "0.1",
|
||||
"title": "Adding 2 numbers together",
|
||||
"version": "0.2",
|
||||
"url": "examples/adding.json",
|
||||
"enabled": 1
|
||||
},
|
||||
{
|
||||
"title": "Empty Canvas",
|
||||
"version": "0.1",
|
||||
"url": "examples/empty.json",
|
||||
"enabled": 1
|
||||
}
|
||||
]
|
||||
}
|
1
out/examples/adding.json
Normal file
1
out/examples/adding.json
Normal file
@ -0,0 +1 @@
|
||||
{"model-version":"3","pc_model":{"pc":{"addressBus":0,"dataBus":0,"instructionReg":0,"programmCounter":0,"uCounter":0,"accumulator":0,"ram":[[100013,"Load ValB to Acc"],[300000,"Acc ++"],[200013,"Store Acc to ValB"],[100012,"Load ValA"],[400000,"Acc --"],[200012,"Store Acc to ValA"],[600008,"Jmp If eq 0"],[500000,"Jmp #000"],[0,"END OF PROGRAM"],[0,""],[0,""],[0,""],[7,"ValA"],[14,"ValB + Result"],[0,""],[0,""],[0,""]]},"uCodes":["pc2ab","ram2db","db2ir","pcInc","ir2uc","n","n","n","n","n","ir2ab","ram2db","db2acc","ucReset","n","n","n","n","n","n","acc2db","ir2ab","db2ram","ucReset","n","n","n","n","n","n","accInc","ucReset","n","n","n","n","n","n","n","n","accDec","ucReset","n","n","n","n","n","n","n","n","ir2pc","ucReset","n","n","n","n","n","n","n","n","ir2pciacceq0","ucReset","n","n","n","n","n","n","n","n"]},"autoscroll":true}
|
1
out/examples/empty.json
Normal file
1
out/examples/empty.json
Normal file
@ -0,0 +1 @@
|
||||
{"model-version":"3","pc_model":{"pc":{"addressBus":0,"dataBus":0,"instructionReg":0,"programmCounter":0,"uCounter":0,"accumulator":0,"ram":[[0,""],[0,""],[0,""],[0,""],[0,""],[0,""],[0,""],[0,""],[0,""],[0,""],[0,""]]},"uCodes":["pc2ab","ram2db","db2ir","pcInc","ir2uc","n","n","n","n","n","ir2ab","ram2db","db2acc","ucReset","n","n","n","n","n","n","acc2db","ir2ab","db2ram","ucReset","n","n","n","n","n","n","accInc","ucReset","n","n","n","n","n","n","n","n"]},"autoscroll":true}
|
@ -1 +1 @@
|
||||
{"model-version":1,"pc":{"addressBus":0,"dataBus":0,"instructionReg":0,"programmCounter":0,"uCounter":0,"accumulator":0,"ram":[100005,300000,200005,400000,0,5,0,0,0,0,0]},"uCode":["pc2ab","ram2db","db2ir","pcInc","ir2uc","n","n","n","n","n","ir2ab","ram2db","db2acc","ucReset","n","n","n","n","n","n","acc2db","ir2ab","db2ram","ucReset","n","n","n","n","n","n","accInc","ucReset","n","n","n","n","n","n","n","n","ir2pc","ucReset","n","n","n","n","n","n","n","n"],"autoscroll":true}
|
||||
{"model-version":"3","pc_model":{"pc":{"addressBus":0,"dataBus":0,"instructionReg":0,"programmCounter":0,"uCounter":0,"accumulator":0,"ram":[[100005,"LoadA #005"],[300000,"IncA"],[200005,"StoreA #005"],[400000,"JMP #000"],[0,""],[5,"val"],[0,""],[0,""],[0,""],[0,""],[0,""]]},"uCodes":["pc2ab","ram2db","db2ir","pcInc","ir2uc","n","n","n","n","n","ir2ab","ram2db","db2acc","ucReset","n","n","n","n","n","n","acc2db","ir2ab","db2ram","ucReset","n","n","n","n","n","n","accInc","ucReset","n","n","n","n","n","n","n","n","ir2pc","ucReset","n","n","n","n","n","n","n","n"]},"autoscroll":true}
|
@ -10,7 +10,7 @@
|
||||
|
||||
<!-- Mobile Specific Metas
|
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
|
||||
|
||||
<!-- CSS
|
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– -->
|
||||
@ -19,6 +19,7 @@
|
||||
<link rel="stylesheet" href="css/cookie.css" />
|
||||
<link rel="stylesheet" href="css/colors-light.css">
|
||||
<link rel="stylesheet" href="css/colors-dark.css">
|
||||
<link rel="stylesheet" href="css/loader.css" />
|
||||
<link rel="stylesheet" href="css/pc.css" />
|
||||
<link rel="stylesheet" href="css/style.css" />
|
||||
|
||||
@ -370,8 +371,8 @@
|
||||
<footer>
|
||||
<div class="container">
|
||||
<p>
|
||||
Made with ☕
|
||||
by <a href="https://github.com/ChrisgammaDE" target="_blank">Christian</a>
|
||||
Made with ☕ <br>
|
||||
© <a href="https://github.com/ChrisgammaDE" target="_blank">Christian</a>, 2021
|
||||
</p>
|
||||
<p>
|
||||
<a href="https://yokta.de/i/impressum.html" target="_blank">Impressum</a>
|
||||
|
8539
out/js/elm.js
8539
out/js/elm.js
File diff suppressed because it is too large
Load Diff
42
out/js/pc.js
42
out/js/pc.js
@ -1,9 +1,15 @@
|
||||
// Init Elm
|
||||
var localStuff = localStorage.getItem("pc_data");
|
||||
if (typeof localStuff !== "string") localStuff = "";
|
||||
|
||||
var app = Elm.Main.init({
|
||||
node: document.getElementById("elm"),
|
||||
// flags: Date.now()
|
||||
flags: localStuff
|
||||
});
|
||||
|
||||
// ###################################################################
|
||||
// ###################################################################
|
||||
|
||||
// Dom Objects
|
||||
let pc = document.getElementsByClassName("pc")[0];
|
||||
let pc_ram = pc.getElementsByClassName("ram")[0];
|
||||
@ -41,36 +47,11 @@ function scrollToCurrent(){
|
||||
// pc.scrollIntoView();
|
||||
}
|
||||
|
||||
// ###################################################################
|
||||
// ###################################################################
|
||||
|
||||
function shrinkTableHead(scroll){
|
||||
let scroller = scroll.target;
|
||||
let pos = scroller.scrollTop;
|
||||
let thead = scroller.getElementsByClassName("head")[0];
|
||||
|
||||
if( pos > 70 ){
|
||||
thead.classList.add("shrunk");
|
||||
}else if (pos < 40){
|
||||
thead.classList.remove("shrunk");
|
||||
}
|
||||
thead.classList.add("shrunk");
|
||||
|
||||
}
|
||||
|
||||
function loadStorage() {
|
||||
let content = localStorage.getItem("pc_data");
|
||||
if( typeof content == "string" ){
|
||||
app.ports.localStorageRecieve.send( content );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Load last state of pc
|
||||
loadStorage();
|
||||
|
||||
// EVENT LISTENERS
|
||||
pc_ram_scroller.addEventListener("scroll", shrinkTableHead);
|
||||
pc_cu_scroller.addEventListener("scroll", shrinkTableHead);
|
||||
|
||||
// Recieve Elm updates via ports
|
||||
app.ports.sendUUpdate.subscribe( (message) => {
|
||||
@ -87,3 +68,8 @@ app.ports.localStorageSend.subscribe( (message) => {
|
||||
if( cookieAccepted() )
|
||||
localStorage.setItem("pc_data", message);
|
||||
} );
|
||||
|
||||
|
||||
// ###################################################################
|
||||
// ###################################################################
|
||||
// Done.
|
@ -1,26 +0,0 @@
|
||||
let text_de = document.getElementById("langDE");
|
||||
let text_en = document.getElementById("langEN");
|
||||
|
||||
let btn_changeToDe = document.getElementById("langPickerDE");
|
||||
let btn_changeToEn = document.getElementById("langPickerEN");
|
||||
|
||||
let lang = (typeof document.documentElement.lang == "string") ? document.documentElement.lang: "en"
|
||||
|
||||
|
||||
function changeLang(lang){
|
||||
if(lang == "de"){
|
||||
text_de.classList.remove("hidden");
|
||||
text_en.classList.add("hidden");
|
||||
}else{
|
||||
text_en.classList.remove("hidden");
|
||||
text_de.classList.add("hidden");
|
||||
}
|
||||
}
|
||||
|
||||
btn_changeToEn.addEventListener("click", () => { changeLang("en") } );
|
||||
btn_changeToDe.addEventListener("click", () => { changeLang("de") } );
|
||||
|
||||
|
||||
|
||||
// Do stuff on loading
|
||||
changeLang( lang );
|
1480
src/Main.elm
1480
src/Main.elm
File diff suppressed because it is too large
Load Diff
107
src/PC/Defaults.elm
Normal file
107
src/PC/Defaults.elm
Normal file
@ -0,0 +1,107 @@
|
||||
module PC.Defaults exposing (..)
|
||||
|
||||
import Array exposing (Array)
|
||||
|
||||
import PC.Types exposing (..)
|
||||
import PC.UActions exposing (..)
|
||||
|
||||
|
||||
initalModel : PC_Model
|
||||
initalModel =
|
||||
{ pc = initialPC
|
||||
, uCodes = initialUCodes
|
||||
}
|
||||
|
||||
initialPC : PC
|
||||
initialPC =
|
||||
{ ram = initialRam
|
||||
, dataBus = 0
|
||||
, addressBus = 0
|
||||
, instructionReg = 0
|
||||
, programmCounter = 0
|
||||
, uCounter = 0
|
||||
, accumulator = 0
|
||||
}
|
||||
|
||||
|
||||
initialRam : Array (Int, String)
|
||||
initialRam = Array.fromList
|
||||
[ (100005, "LoadA #005") -- 000 -- LoadA #005
|
||||
, (300000, "IncA") -- 001 -- IncA
|
||||
, (200005, "StoreA #005") -- 002 -- StoreA #005
|
||||
, (400000, "JMP #000") -- 003 -- JMP #000
|
||||
, (0,"") -- 004
|
||||
, (5,"val") -- 005
|
||||
, (0, "") -- 006
|
||||
, (0, "") -- 007
|
||||
, (0, "") -- 008
|
||||
, (0, "") -- 009
|
||||
, (0, "") -- 010
|
||||
]
|
||||
|
||||
|
||||
|
||||
initialUCodes : Array UAction
|
||||
initialUCodes = Array.fromList
|
||||
[ UA_ProgrammCounter2AddressBus -- 000
|
||||
, UA_Ram2DataBus -- 001
|
||||
, UA_DataBus2InstructionReg -- 002
|
||||
, UA_ProgrammCounterIncrement -- 003
|
||||
, UA_InstructionReg2UCounter -- 004
|
||||
, UA_Nothing -- 005
|
||||
, UA_Nothing
|
||||
, UA_Nothing
|
||||
, UA_Nothing
|
||||
, UA_Nothing -- 009
|
||||
|
||||
-- 010 LOADA
|
||||
, UA_InstructionReg2AddressBus -- 010
|
||||
, UA_Ram2DataBus -- 011
|
||||
, UA_DataBus2Accumulator -- 012
|
||||
, UA_ResetUCounter -- 013
|
||||
, UA_Nothing -- 014
|
||||
, UA_Nothing
|
||||
, UA_Nothing
|
||||
, UA_Nothing
|
||||
, UA_Nothing
|
||||
, UA_Nothing -- 019
|
||||
|
||||
-- 020 STOA
|
||||
, UA_Accumulator2DataBus -- 020
|
||||
, UA_InstructionReg2AddressBus -- 021
|
||||
, UA_DataBus2Ram -- 022
|
||||
, UA_ResetUCounter -- 023
|
||||
, UA_Nothing --024
|
||||
, UA_Nothing
|
||||
, UA_Nothing
|
||||
, UA_Nothing
|
||||
, UA_Nothing
|
||||
, UA_Nothing -- 029
|
||||
|
||||
-- 030 INCA
|
||||
, UA_AccumulatorIncrement -- 030
|
||||
, UA_ResetUCounter -- 031
|
||||
, UA_Nothing -- 032
|
||||
, UA_Nothing
|
||||
, UA_Nothing
|
||||
, UA_Nothing
|
||||
, UA_Nothing
|
||||
, UA_Nothing
|
||||
, UA_Nothing
|
||||
, UA_Nothing -- 039
|
||||
|
||||
-- 040 JMP
|
||||
, UA_InstructionReg2ProgrammCounter -- 040
|
||||
, UA_ResetUCounter -- 041
|
||||
, UA_Nothing -- 042
|
||||
, UA_Nothing
|
||||
, UA_Nothing
|
||||
, UA_Nothing
|
||||
, UA_Nothing
|
||||
, UA_Nothing
|
||||
, UA_Nothing
|
||||
, UA_Nothing -- 049
|
||||
]
|
||||
|
||||
|
||||
|
92
src/PC/Helpers.elm
Normal file
92
src/PC/Helpers.elm
Normal file
@ -0,0 +1,92 @@
|
||||
module PC.Helpers exposing (..)
|
||||
|
||||
import Array exposing (Array)
|
||||
import Http exposing (..)
|
||||
|
||||
-- Convert a number from 42 to 0042
|
||||
-- number : (Prefered positive) whole number
|
||||
-- length : positive whole number
|
||||
-- Please note that only 0 are added. The number will not be shortend!
|
||||
addLeadingZero : Int -> Int -> String
|
||||
addLeadingZero number length =
|
||||
let
|
||||
num_str = String.fromInt number
|
||||
in
|
||||
(String.fromList <| List.repeat (length - String.length num_str) '0'
|
||||
)
|
||||
++ num_str
|
||||
|
||||
|
||||
-- Get the value at a given position in a List.
|
||||
-- For performance reasons it might be better
|
||||
-- to use an Array instead.
|
||||
valueAt : Int -> List a -> Maybe a
|
||||
valueAt pos list = List.head <| List.drop pos list
|
||||
|
||||
|
||||
-- Change the value at a given position in a List.
|
||||
-- If your pos is greater than the length of
|
||||
-- the list, then the rest is filled with the
|
||||
-- default element.
|
||||
overwriteAt : a -> Int -> a ->List a -> List a
|
||||
overwriteAt default pos newVal list =
|
||||
let
|
||||
len = List.length list
|
||||
in
|
||||
if pos > len then
|
||||
list ++
|
||||
(List.repeat (pos-len) default) ++
|
||||
[newVal]
|
||||
else
|
||||
let
|
||||
before = List.take pos list
|
||||
after = List.drop (pos+1) list
|
||||
in
|
||||
before ++ [newVal] ++ after
|
||||
|
||||
overwriteAt_Arr : a -> Int -> a -> Array a -> Array a
|
||||
overwriteAt_Arr default pos newVal list =
|
||||
let
|
||||
len = Array.length list
|
||||
in
|
||||
if pos > len then
|
||||
Array.append list
|
||||
<| Array.append (Array.repeat (pos-len) default)
|
||||
<| Array.fromList [newVal]
|
||||
else
|
||||
Array.set pos newVal list
|
||||
|
||||
|
||||
-- Prints Http Errors into something readable
|
||||
printHttpError : Http.Error -> String
|
||||
printHttpError err =
|
||||
case err of
|
||||
Http.BadUrl str -> "Bad Url: " ++ str
|
||||
Http.Timeout -> "Timeout"
|
||||
Http.NetworkError -> "Network Error"
|
||||
Http.BadStatus num -> "Bad Status: " ++ String.fromInt num
|
||||
Http.BadBody str -> "Bad Body: " ++ str
|
||||
|
||||
|
||||
seperateInstructionsEntry : Int -> (Int, Int)
|
||||
seperateInstructionsEntry i =
|
||||
let
|
||||
instruction = i // 100000
|
||||
address = i - instruction*100000
|
||||
in
|
||||
(instruction, address)
|
||||
|
||||
|
||||
valueAtRam : Int -> Array (Int, String) -> (Int, String)
|
||||
valueAtRam pos arr =
|
||||
case Array.get pos arr of
|
||||
Just a -> a
|
||||
Nothing -> (0, "")
|
||||
|
||||
|
||||
changeAtRam : Int -> Int -> Array (Int, String) -> Array (Int,String)
|
||||
changeAtRam pos newVal list =
|
||||
let
|
||||
(_,comment) = valueAtRam pos list
|
||||
in
|
||||
overwriteAt_Arr (0, "") pos (newVal, comment) list
|
112
src/PC/JSON.elm
Normal file
112
src/PC/JSON.elm
Normal file
@ -0,0 +1,112 @@
|
||||
module PC.Json exposing ( pcModelDecoder
|
||||
, pcModelEncoder
|
||||
, tuple2Decoder
|
||||
, tuple2Encoder
|
||||
)
|
||||
|
||||
import PC.Types exposing (..)
|
||||
import Maybe
|
||||
import Array exposing (Array)
|
||||
|
||||
import Json.Encode as JE exposing (Value)
|
||||
import Json.Decode as JD exposing (Decoder)
|
||||
|
||||
import PC.Types exposing (..)
|
||||
import PC.UActions exposing (..)
|
||||
|
||||
|
||||
-- ##########################################################
|
||||
-- Decoders
|
||||
-- ##########################################################
|
||||
|
||||
pcModelDecoder : Decoder PC_Model
|
||||
pcModelDecoder =
|
||||
JD.map2
|
||||
PC_Model
|
||||
(JD.field "pc" pcDecoder)
|
||||
(JD.field "uCodes" uCodeDecoder)
|
||||
|
||||
|
||||
pcDecoder : Decoder PC
|
||||
pcDecoder =
|
||||
JD.map7
|
||||
PC
|
||||
(JD.field "ram" <| JD.array <| tuple2Decoder JD.int JD.string)
|
||||
(JD.field "dataBus" JD.int)
|
||||
(JD.field "addressBus" JD.int)
|
||||
(JD.field "instructionReg" JD.int)
|
||||
(JD.field "programmCounter" JD.int)
|
||||
(JD.field "uCounter" JD.int)
|
||||
(JD.field "accumulator" JD.int)
|
||||
|
||||
uCodeDecoder : Decoder (Array UAction)
|
||||
uCodeDecoder =
|
||||
JD.array <| JD.map uActionDecoder JD.string
|
||||
|
||||
uActionDecoder : String -> UAction
|
||||
uActionDecoder str =
|
||||
Maybe.withDefault UA_Nothing <| string2uAction str
|
||||
|
||||
|
||||
|
||||
tuple2Decoder : Decoder a -> Decoder b -> Decoder (a,b)
|
||||
tuple2Decoder enc1 enc2 =
|
||||
JD.map2 Tuple.pair
|
||||
(JD.index 0 enc1)
|
||||
(JD.index 1 enc2)
|
||||
|
||||
-- ##########################################################
|
||||
-- ##########################################################
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
-- ##########################################################
|
||||
-- Encoders
|
||||
-- ##########################################################
|
||||
|
||||
pcModelEncoder : PC_Model -> Value
|
||||
pcModelEncoder model =
|
||||
JE.object
|
||||
[ ( "pc" , pcEncoder model.pc )
|
||||
, ( "uCodes" , uCodesEncoder model.uCodes )
|
||||
]
|
||||
|
||||
pcEncoder : PC -> Value
|
||||
pcEncoder pc =
|
||||
JE.object
|
||||
[ ( "addressBus" , JE.int pc.addressBus )
|
||||
, ( "dataBus" , JE.int pc.dataBus )
|
||||
, ( "instructionReg" , JE.int pc.instructionReg )
|
||||
, ( "programmCounter" , JE.int pc.programmCounter )
|
||||
, ( "uCounter" , JE.int pc.uCounter )
|
||||
, ( "accumulator" , JE.int pc.accumulator )
|
||||
, ( "ram" , ramEncoder pc.ram )
|
||||
]
|
||||
|
||||
ramEncoder : Array (Int, String) -> Value
|
||||
ramEncoder arr =
|
||||
JE.array
|
||||
(tuple2Encoder JE.int JE.string)
|
||||
arr
|
||||
|
||||
uCodesEncoder : Array UAction -> Value
|
||||
uCodesEncoder uActions =
|
||||
JE.array encodeSingleuCode uActions
|
||||
|
||||
encodeSingleuCode : UAction -> Value
|
||||
encodeSingleuCode action =
|
||||
let
|
||||
uCode = uAction2UCode action
|
||||
in
|
||||
JE.string uCode.id
|
||||
|
||||
|
||||
tuple2Encoder : (a -> Value) -> (b -> Value) -> (a,b) -> Value
|
||||
tuple2Encoder encA encB (valA, valB) =
|
||||
JE.list identity [ encA valA, encB valB ]
|
||||
|
||||
-- ##########################################################
|
||||
-- ##########################################################
|
||||
-- Done.
|
28
src/PC/PC.elm
Normal file
28
src/PC/PC.elm
Normal file
@ -0,0 +1,28 @@
|
||||
module PC.PC exposing (..)
|
||||
|
||||
import Html exposing (Html)
|
||||
--import Json.Encode as JE
|
||||
import Json.Decode as JD
|
||||
|
||||
import PC.Types exposing (..)
|
||||
import PC.Defaults exposing (..)
|
||||
import PC.Helpers exposing (..)
|
||||
import PC.Update exposing (..)
|
||||
import PC.View exposing (..)
|
||||
|
||||
|
||||
|
||||
update : PC_Msg -> PC_Model -> (PC_Model, PC_AfterUpdateAction)
|
||||
update = pc_update
|
||||
|
||||
|
||||
view : PC_Model -> Html PC_Msg
|
||||
view = pc_view
|
||||
|
||||
init : PC_Model
|
||||
init = initalModel
|
||||
|
||||
|
||||
|
||||
|
||||
|
78
src/PC/Types.elm
Normal file
78
src/PC/Types.elm
Normal file
@ -0,0 +1,78 @@
|
||||
module PC.Types exposing (..)
|
||||
|
||||
import Array exposing (Array)
|
||||
|
||||
pcModelVersion = "3"
|
||||
|
||||
type alias PC_Model =
|
||||
{ pc : PC
|
||||
, uCodes : Array UAction
|
||||
}
|
||||
|
||||
type alias PC =
|
||||
{ ram : Array (Int, String)
|
||||
, dataBus : Int
|
||||
, addressBus : Int
|
||||
, instructionReg : Int
|
||||
, programmCounter : Int
|
||||
, uCounter : Int
|
||||
, accumulator : Int
|
||||
}
|
||||
|
||||
type alias UCode =
|
||||
{ variant : UAction
|
||||
, id : String
|
||||
, action : PC -> PC
|
||||
, label : String
|
||||
}
|
||||
|
||||
type UAction
|
||||
= UA_Accumulator2DataBus
|
||||
| UA_AccumulatorDecrement
|
||||
| UA_AccumulatorIncrement
|
||||
| UA_DataBus2Accumulator
|
||||
| UA_DataBus2InstructionReg
|
||||
| UA_DataBus2Ram
|
||||
| UA_InstructionReg2AddressBus
|
||||
| UA_InstructionReg2ProgrammCounter
|
||||
| UA_InstructionReg2UCounter
|
||||
| UA_ProgrammCounterIncrement
|
||||
| UA_InstructionReg2ProgrammCounterIfAccEq0
|
||||
| UA_Ram2DataBus
|
||||
| UA_ResetUCounter
|
||||
| UA_ProgrammCounter2AddressBus
|
||||
| UA_Nothing
|
||||
|
||||
|
||||
-- To make it easier to understand everything has name convention
|
||||
-- PM_ -> PC_Msg in general
|
||||
-- PM_B_ -> for a Button
|
||||
-- PM_C_ -> for a Checkbox
|
||||
-- PM_F_ -> for a TextField
|
||||
type PC_Msg
|
||||
= PM_B_UCycleStep
|
||||
| PM_B_InstructionStep
|
||||
| PM_B_Reset
|
||||
| PM_B_RamAddBelow
|
||||
| PM_B_CuAddBelow
|
||||
| PM_F_RamEditInstr Int String
|
||||
| PM_F_RamEditAddress Int String
|
||||
| PM_F_RamEditComment Int String
|
||||
| PM_F_CuEditAction Int String
|
||||
| PM_F_CuInstrRegEditAddr String
|
||||
| PM_F_CuInstrRegEditInstr String
|
||||
| PM_F_CuProgCounterEdit String
|
||||
| PM_F_CuUCounterEdit String
|
||||
| PM_F_EditAddressBus String
|
||||
| PM_F_EditDataBus String
|
||||
| PM_F_AluEdit String
|
||||
| PM_ManualStep UAction
|
||||
|
||||
|
||||
-- Tells main what is supposed
|
||||
-- to happen after a update
|
||||
type PC_AfterUpdateAction
|
||||
= PUA_Nothing -- Do nothing
|
||||
| PUA_Storage -- Update localStorage
|
||||
| PUA_Scroller -- Scroll to value
|
||||
| PUA_Storage_And_Scroller -- Update localStorage and scroll to values
|
163
src/PC/UActions.elm
Normal file
163
src/PC/UActions.elm
Normal file
@ -0,0 +1,163 @@
|
||||
module PC.UActions exposing ( uCodes
|
||||
, uAction2Label
|
||||
, string2uAction
|
||||
, uAction2UCode )
|
||||
|
||||
import Array exposing (Array)
|
||||
import Tuple
|
||||
|
||||
import PC.Types exposing (..)
|
||||
import PC.Helpers exposing (..)
|
||||
|
||||
uCodes : List UCode
|
||||
uCodes =
|
||||
[ UCode UA_Accumulator2DataBus "acc2db" actAccumulator2DataBus "Acc -> DataBus"
|
||||
, UCode UA_AccumulatorDecrement "accDec" actAccumulatorDecrement "Acc --"
|
||||
, UCode UA_AccumulatorIncrement "accInc" actAccumulatorIncrement "Acc ++"
|
||||
, UCode UA_DataBus2Accumulator "db2acc" actDataBus2Accumulator "DataBus -> Acc"
|
||||
, UCode UA_DataBus2InstructionReg "db2ir" actDataBus2InstructionReg "DataBus -> InstReg"
|
||||
, UCode UA_DataBus2Ram "db2ram" actDataBus2Ram "DataBus -> Ram"
|
||||
, UCode UA_InstructionReg2AddressBus "ir2ab" actInstructionReg2AddressBus "InstReg -> AddrBus"
|
||||
, UCode UA_InstructionReg2ProgrammCounter "ir2pc" actInstructionReg2ProgrammCounter "InstReg -> ProgCount"
|
||||
, UCode UA_InstructionReg2UCounter "ir2uc" actInstructionReg2UCounter "InstReg -> µCounter"
|
||||
, UCode UA_ProgrammCounterIncrement "pcInc" actProgrammCounterIncrement "ProgCounter ++"
|
||||
, UCode UA_Ram2DataBus "ram2db" actRam2DataBus "Ram -> DataBus"
|
||||
, UCode UA_ResetUCounter "ucReset" actResetUCounter "µCounter = 0"
|
||||
, UCode UA_ProgrammCounter2AddressBus "pc2ab" actProgrammCounter2AddressBus "ProgCounter -> AddrBus"
|
||||
, UCode UA_Nothing "n" (\s -> s) "Empty"
|
||||
, UCode UA_InstructionReg2ProgrammCounterIfAccEq0
|
||||
"ir2pciacceq0" actInstructionReg2ProgrammCounterIfAccEq0 "Acc == 0 => InstReg -> ProgCounter"
|
||||
]
|
||||
|
||||
|
||||
-- #######################################################################################
|
||||
-- ACTIONS
|
||||
-- #######################################################################################
|
||||
|
||||
actRam2DataBus : PC -> PC
|
||||
actRam2DataBus pc =
|
||||
let
|
||||
ab =
|
||||
pc.addressBus
|
||||
|
||||
db =
|
||||
Tuple.first <| valueAtRam ab pc.ram
|
||||
in
|
||||
{ pc | dataBus = db }
|
||||
|
||||
|
||||
actDataBus2InstructionReg : PC -> PC
|
||||
actDataBus2InstructionReg pc =
|
||||
{ pc | instructionReg = pc.dataBus }
|
||||
|
||||
|
||||
actResetUCounter : PC -> PC
|
||||
actResetUCounter pc =
|
||||
{ pc | uCounter = 0 }
|
||||
|
||||
|
||||
actInstructionReg2UCounter : PC -> PC
|
||||
actInstructionReg2UCounter pc =
|
||||
-- Multiply by ten, because every instruction is 10 uCodes long
|
||||
let
|
||||
(instruction, address) = seperateInstructionsEntry pc.instructionReg
|
||||
in
|
||||
{ pc | uCounter = instruction * 10}
|
||||
|
||||
|
||||
actInstructionReg2AddressBus : PC -> PC
|
||||
actInstructionReg2AddressBus pc =
|
||||
let
|
||||
(instruction, address) = seperateInstructionsEntry pc.instructionReg
|
||||
in
|
||||
{ pc | addressBus = address }
|
||||
|
||||
|
||||
actInstructionReg2ProgrammCounter : PC -> PC
|
||||
actInstructionReg2ProgrammCounter pc =
|
||||
let
|
||||
(instruction, address) = seperateInstructionsEntry pc.instructionReg
|
||||
in
|
||||
|
||||
{ pc | programmCounter = address }
|
||||
|
||||
|
||||
actProgrammCounterIncrement : PC -> PC
|
||||
actProgrammCounterIncrement pc =
|
||||
{ pc | programmCounter = pc.programmCounter + 1 }
|
||||
|
||||
|
||||
actProgrammCounter2AddressBus : PC -> PC
|
||||
actProgrammCounter2AddressBus pc =
|
||||
{ pc | addressBus = pc.programmCounter }
|
||||
|
||||
actInstructionReg2ProgrammCounterIfAccEq0 : PC -> PC
|
||||
actInstructionReg2ProgrammCounterIfAccEq0 pc =
|
||||
if pc.accumulator == 0 then
|
||||
let
|
||||
(_,addr) = seperateInstructionsEntry pc.instructionReg
|
||||
in
|
||||
{ pc | programmCounter = addr }
|
||||
else
|
||||
pc
|
||||
|
||||
actDataBus2Accumulator : PC -> PC
|
||||
actDataBus2Accumulator pc =
|
||||
{ pc | accumulator = pc.dataBus }
|
||||
|
||||
|
||||
actAccumulator2DataBus : PC -> PC
|
||||
actAccumulator2DataBus pc =
|
||||
{ pc | dataBus = pc.accumulator }
|
||||
|
||||
|
||||
actAccumulatorIncrement : PC -> PC
|
||||
actAccumulatorIncrement pc =
|
||||
{ pc | accumulator = pc.accumulator + 1 }
|
||||
|
||||
|
||||
actAccumulatorDecrement : PC -> PC
|
||||
actAccumulatorDecrement pc =
|
||||
{ pc | accumulator = pc.accumulator - 1 }
|
||||
|
||||
|
||||
actDataBus2Ram : PC -> PC
|
||||
actDataBus2Ram pc =
|
||||
let
|
||||
newRam =
|
||||
changeAtRam pc.addressBus pc.dataBus pc.ram
|
||||
in
|
||||
{ pc | ram = newRam }
|
||||
|
||||
|
||||
-- #################################################################
|
||||
-- Helpers
|
||||
-- #################################################################
|
||||
|
||||
uAction2Label : UAction -> String
|
||||
uAction2Label variant =
|
||||
let
|
||||
filtered_list = List.filter (\u -> u.variant == variant ) uCodes
|
||||
in
|
||||
case List.head filtered_list of
|
||||
Just uCode -> uCode.label
|
||||
Nothing -> "IDK"
|
||||
|
||||
uAction2UCode : UAction -> UCode
|
||||
uAction2UCode variant =
|
||||
let
|
||||
filtered_list = List.filter (\u -> u.variant == variant ) uCodes
|
||||
in
|
||||
case List.head filtered_list of
|
||||
Just uCode -> uCode
|
||||
Nothing -> UCode UA_Nothing "n" (\s -> s) "Empty"
|
||||
|
||||
string2uAction : String -> Maybe UAction
|
||||
string2uAction str =
|
||||
let
|
||||
filtered_list = List.filter (\u -> u.id == str) uCodes
|
||||
in
|
||||
case List.head filtered_list of
|
||||
Just uCode -> Just uCode.variant
|
||||
_ -> Nothing
|
||||
|
246
src/PC/Update.elm
Normal file
246
src/PC/Update.elm
Normal file
@ -0,0 +1,246 @@
|
||||
module PC.Update exposing (pc_update)
|
||||
|
||||
import Array exposing (Array)
|
||||
|
||||
import PC.Types exposing (..)
|
||||
import PC.UActions exposing (..)
|
||||
import PC.Defaults exposing (..)
|
||||
import PC.Helpers exposing (..)
|
||||
|
||||
|
||||
pc_update : PC_Msg -> PC_Model -> (PC_Model, PC_AfterUpdateAction)
|
||||
pc_update msg model =
|
||||
case msg of
|
||||
PM_B_UCycleStep ->
|
||||
( uStepPC model
|
||||
, if model.pc.uCounter == 0 then PUA_Storage_And_Scroller
|
||||
else PUA_Scroller
|
||||
)
|
||||
|
||||
PM_B_InstructionStep ->
|
||||
( executeInstruction model
|
||||
, PUA_Storage_And_Scroller )
|
||||
|
||||
|
||||
PM_B_Reset ->
|
||||
( { model | pc = { initialPC | ram = model.pc.ram } }
|
||||
, PUA_Storage_And_Scroller )
|
||||
|
||||
PM_B_RamAddBelow ->
|
||||
let
|
||||
old_pc = model.pc
|
||||
new_pc = {old_pc | ram = Array.append old_pc.ram <| Array.fromList [(0, "")]}
|
||||
in
|
||||
({model | pc = new_pc}
|
||||
, PUA_Storage)
|
||||
|
||||
PM_B_CuAddBelow ->
|
||||
({model | uCodes = Array.append model.uCodes <| Array.repeat 10 UA_Nothing}
|
||||
, PUA_Storage)
|
||||
|
||||
PM_F_RamEditAddress addr may_int ->
|
||||
case String.toInt may_int of
|
||||
Just int ->
|
||||
let
|
||||
(inst,_) = seperateInstructionsEntry ( Tuple.first <| valueAtRam addr model.pc.ram )
|
||||
new_val = inst * 100000 + int
|
||||
old_pc = model.pc
|
||||
new_pc = { old_pc | ram = (changeAtRam addr new_val old_pc.ram) }
|
||||
in
|
||||
({ model | pc = new_pc }, PUA_Storage)
|
||||
_ -> (model, PUA_Nothing)
|
||||
|
||||
PM_F_RamEditInstr addr may_int ->
|
||||
case String.toInt may_int of
|
||||
Just int ->
|
||||
let
|
||||
(_,address) = seperateInstructionsEntry ( Tuple.first <| valueAtRam addr model.pc.ram )
|
||||
new_val = int * 100000 + address
|
||||
old_pc = model.pc
|
||||
new_pc = { old_pc | ram = (changeAtRam addr new_val old_pc.ram) }
|
||||
in
|
||||
({ model | pc = new_pc }, PUA_Storage)
|
||||
_ -> ( model, PUA_Nothing )
|
||||
|
||||
|
||||
PM_F_RamEditComment addr str ->
|
||||
let
|
||||
(val, _) = valueAtRam addr model.pc.ram
|
||||
old_pc = model.pc
|
||||
new_pc = { old_pc | ram = overwriteAt_Arr (0,"") addr (val, str) old_pc.ram }
|
||||
in
|
||||
({ model | pc = new_pc }, PUA_Storage)
|
||||
|
||||
PM_F_CuEditAction addr may_action ->
|
||||
case string2uAction may_action of
|
||||
Just action ->
|
||||
let
|
||||
newCode = Array.set addr action model.uCodes
|
||||
in
|
||||
({ model | uCodes = newCode }, PUA_Storage)
|
||||
_ -> ( model, PUA_Nothing )
|
||||
|
||||
|
||||
PM_F_CuInstrRegEditAddr text ->
|
||||
case String.toInt text of
|
||||
Just int ->
|
||||
let old_pc = model.pc
|
||||
(instr,_) = seperateInstructionsEntry old_pc.instructionReg
|
||||
new_pc = { old_pc | instructionReg = instr * 100000 + int }
|
||||
in
|
||||
({ model | pc = new_pc }, PUA_Storage)
|
||||
_ -> ( model, PUA_Nothing )
|
||||
|
||||
PM_F_CuInstrRegEditInstr text ->
|
||||
case String.toInt text of
|
||||
Just int ->
|
||||
let old_pc = model.pc
|
||||
(_,addr) = seperateInstructionsEntry old_pc.instructionReg
|
||||
new_pc = { old_pc | instructionReg = int * 100000 + addr }
|
||||
in
|
||||
({ model | pc = new_pc }, PUA_Storage)
|
||||
_ -> ( model, PUA_Nothing )
|
||||
|
||||
PM_F_CuProgCounterEdit text ->
|
||||
case String.toInt text of
|
||||
Just int ->
|
||||
let old_pc = model.pc
|
||||
new_pc = { old_pc | programmCounter = int }
|
||||
in
|
||||
({ model | pc = new_pc }, PUA_Storage)
|
||||
_ -> ( model, PUA_Nothing )
|
||||
|
||||
PM_F_CuUCounterEdit text ->
|
||||
case String.toInt text of
|
||||
Just int ->
|
||||
let old_pc = model.pc
|
||||
new_pc = { old_pc | uCounter = int }
|
||||
in
|
||||
( { model | pc = new_pc }, PUA_Storage_And_Scroller )
|
||||
_ -> ( model, PUA_Nothing )
|
||||
|
||||
PM_F_EditAddressBus text ->
|
||||
case String.toInt text of
|
||||
Just int ->
|
||||
let old_pc = model.pc
|
||||
new_pc = { old_pc | addressBus = int }
|
||||
in
|
||||
( { model | pc = new_pc }, PUA_Storage_And_Scroller )
|
||||
_ -> ( model, PUA_Nothing )
|
||||
|
||||
PM_F_EditDataBus text ->
|
||||
case String.toInt text of
|
||||
Just int ->
|
||||
let old_pc = model.pc
|
||||
new_pc = { old_pc | dataBus = int }
|
||||
in
|
||||
({ model | pc = new_pc }, PUA_Storage)
|
||||
_ -> ( model, PUA_Nothing )
|
||||
|
||||
PM_F_AluEdit text ->
|
||||
case String.toInt text of
|
||||
Just int ->
|
||||
let old_pc = model.pc
|
||||
new_pc = { old_pc | accumulator = int }
|
||||
in
|
||||
({ model | pc = new_pc }, PUA_Storage)
|
||||
_ -> ( model, PUA_Nothing )
|
||||
|
||||
|
||||
PM_ManualStep action ->
|
||||
let
|
||||
instruction = getAction action
|
||||
new_model = { model | pc = instruction model.pc }
|
||||
in
|
||||
( new_model, PUA_Storage_And_Scroller )
|
||||
|
||||
-- ###############################################################################
|
||||
-- ###############################################################################
|
||||
|
||||
|
||||
|
||||
-- ###############################################################################
|
||||
-- Update Helpers
|
||||
-- ###############################################################################
|
||||
|
||||
-- Practically a part of uStepPC but sepeated for manual mode
|
||||
getAction : UAction -> (PC -> PC)
|
||||
getAction uAction =
|
||||
let
|
||||
possible_instructions =
|
||||
List.filter (\u -> u.variant == uAction) uCodes
|
||||
in
|
||||
case List.head possible_instructions of
|
||||
Just uCode ->
|
||||
uCode.action
|
||||
_ ->
|
||||
(\s -> s)
|
||||
|
||||
|
||||
uStepPC : PC_Model -> PC_Model
|
||||
uStepPC model =
|
||||
let
|
||||
uCounter =
|
||||
model.pc.uCounter
|
||||
|
||||
may_code : Maybe UAction
|
||||
may_code = Array.get uCounter model.uCodes
|
||||
--valueAt uCounter model.uCodes
|
||||
in
|
||||
case may_code of
|
||||
Just code ->
|
||||
let
|
||||
-- code :: UAction
|
||||
old_pc = model.pc
|
||||
temp_pc = { old_pc | uCounter = uCounter + 1 }
|
||||
|
||||
uCode = uAction2UCode code
|
||||
f = uCode.action
|
||||
new_pc = f temp_pc
|
||||
in
|
||||
{ model | pc = new_pc }
|
||||
|
||||
|
||||
--let
|
||||
-- possible_instructions =
|
||||
-- List.filter (\s -> Tuple.first s == action) uCodeMaps
|
||||
--in
|
||||
--case List.head possible_instructions of
|
||||
-- Just ( name, instruction ) ->
|
||||
-- let
|
||||
-- old_pc =
|
||||
-- model.pc
|
||||
|
||||
-- new_pc =
|
||||
-- { old_pc | uCounter = old_pc.uCounter + 1 }
|
||||
-- in
|
||||
-- { model | pc = instruction new_pc }
|
||||
|
||||
-- _ ->
|
||||
-- let
|
||||
-- old_pc =
|
||||
-- model.pc
|
||||
|
||||
-- new_pc =
|
||||
-- { old_pc | uCounter = 0 }
|
||||
-- in
|
||||
-- { model | pc = new_pc }
|
||||
|
||||
_ ->
|
||||
model
|
||||
|
||||
|
||||
executeInstruction : PC_Model -> PC_Model
|
||||
executeInstruction model =
|
||||
let
|
||||
new_model = uStepPC model
|
||||
in
|
||||
if new_model.pc.uCounter == 0 then
|
||||
uStepPC new_model
|
||||
else
|
||||
executeInstruction new_model
|
||||
|
||||
|
||||
-- ###############################################################################
|
||||
-- ###############################################################################
|
||||
-- Done.
|
383
src/PC/View.elm
Normal file
383
src/PC/View.elm
Normal file
@ -0,0 +1,383 @@
|
||||
module PC.View exposing (pc_view)
|
||||
|
||||
import Html exposing (Html, button, div, h1, p, text)
|
||||
import Html.Attributes as HAttr exposing (class, classList, value)
|
||||
import Html.Events as HEvent exposing (onClick, onInput)
|
||||
import Html.Lazy exposing (lazy)
|
||||
import Array exposing (Array)
|
||||
import Json.Decode as JD
|
||||
|
||||
import PC.Types exposing (..)
|
||||
import PC.UActions exposing (..)
|
||||
import PC.Helpers exposing (..)
|
||||
|
||||
pc_view : PC_Model -> Html PC_Msg
|
||||
pc_view model = div []
|
||||
[ div
|
||||
[ class "grid-fullwidth", class "grid-addressbus" ]
|
||||
[ lazy viewAddressBus model ]
|
||||
, lazy viewRam model
|
||||
, lazy viewCu model
|
||||
, lazy viewAlu model
|
||||
, div
|
||||
[ class "grid-fullwidth", class "grid-databus" ]
|
||||
[ lazy viewDataBus model ]
|
||||
]
|
||||
|
||||
-- #####################################################################
|
||||
-- #####################################################################
|
||||
|
||||
|
||||
|
||||
-- #####################################################################
|
||||
-- RAM
|
||||
-- #####################################################################
|
||||
|
||||
viewRam : PC_Model -> Html PC_Msg
|
||||
viewRam model =
|
||||
div [ class "section", class "ram" ]
|
||||
[ h1 [ class "header" ] [ text "RAM" ]
|
||||
, div [ class "arrow", class "down", class "top"] [ div [] [] , div [] [] ]
|
||||
, div [ class "scroller" ]
|
||||
[ Html.table [ class "" ]
|
||||
[ Html.thead [ class "head" ]
|
||||
[ Html.tr []
|
||||
[ Html.th [ class "address" ] [ text "Addr" ]
|
||||
, Html.th [] [ text "Value" ]
|
||||
, Html.th [] [ text "Comment" ]
|
||||
]
|
||||
]
|
||||
, lazy viewRamContent model
|
||||
]
|
||||
]
|
||||
, drawArrow Bottom Down UA_Ram2DataBus "Ram -> DataBus"
|
||||
, drawArrow Bottom Up UA_DataBus2Ram "DataBus -> Ram"
|
||||
]
|
||||
|
||||
|
||||
viewRamContent : PC_Model -> Html PC_Msg
|
||||
viewRamContent model =
|
||||
let
|
||||
--indexedRam =
|
||||
-- List.indexedMap Tuple.pair <| Array.toList model.pc.ram
|
||||
|
||||
ram2table : Int -> (Int, String) -> Html PC_Msg
|
||||
ram2table id entry =
|
||||
let
|
||||
(val,comment) = entry
|
||||
|
||||
(instruction, address) = seperateInstructionsEntry val
|
||||
in
|
||||
Html.tr
|
||||
[ classList [ ( "current", id == model.pc.addressBus ) ] ]
|
||||
[ Html.td [ class "num" ] [ text (addLeadingZero id 3) ]
|
||||
, Html.td [ class "num " ]
|
||||
[ Html.input
|
||||
[ HAttr.type_ "number"
|
||||
, HAttr.value <| addLeadingZero instruction 3
|
||||
, onInput <| PM_F_RamEditInstr id
|
||||
, class "ram-entry"
|
||||
, class "instruction"
|
||||
]
|
||||
[]
|
||||
, Html.input
|
||||
[ HAttr.type_ "number"
|
||||
, HAttr.value <| addLeadingZero address 5
|
||||
, onInput <| PM_F_RamEditAddress id
|
||||
, class "ram-entry"
|
||||
, class "address"
|
||||
]
|
||||
[]
|
||||
]
|
||||
, Html.td[ class "comment" ]
|
||||
[ Html.input
|
||||
[ HAttr.type_ "text"
|
||||
, HAttr.value comment
|
||||
, onInput <| PM_F_RamEditComment id ]
|
||||
[]
|
||||
]
|
||||
]
|
||||
in
|
||||
Html.tbody []
|
||||
((Array.toList <| Array.indexedMap ram2table model.pc.ram)
|
||||
++
|
||||
[ Html.tr []
|
||||
[ Html.td [] []
|
||||
, Html.td []
|
||||
[ button
|
||||
[ onClick PM_B_RamAddBelow ]
|
||||
[ text "Add Entry"]
|
||||
]
|
||||
, Html.td [][]
|
||||
]
|
||||
]
|
||||
)
|
||||
|
||||
-- #####################################################################
|
||||
-- #####################################################################
|
||||
|
||||
|
||||
|
||||
|
||||
-- #####################################################################
|
||||
-- Control Unit
|
||||
-- #####################################################################
|
||||
|
||||
viewCu : PC_Model -> Html PC_Msg
|
||||
viewCu model =
|
||||
let
|
||||
( instrRegInst, instrRegAddr ) = seperateInstructionsEntry model.pc.instructionReg
|
||||
in
|
||||
div [ class "section", class "cu" ]
|
||||
[ drawArrow Top Up UA_InstructionReg2AddressBus "InstR -> AddrB"
|
||||
, drawArrow Top Up UA_ProgrammCounter2AddressBus "ProgCounter -> AddrB"
|
||||
--, div [ class "arrow", class "up", class "top"]
|
||||
-- [ div [ class "button" ]
|
||||
-- [ Html.a [ onClick (PM_ManualStep ActInstructionReg2AddressBus)] [ text "InstR -> AddrB" ]]
|
||||
-- , div [] []
|
||||
-- ]
|
||||
--, div [ class "arrow", class "up", class "top", class "arrow2"]
|
||||
-- [ div [ class "button" ]
|
||||
-- [ Html.a [ onClick (PM_ManualStep ActProgrammCounter2AddressBus)] [ text "ProgCounter -> AddrB" ]]
|
||||
-- , div [] []
|
||||
-- ]
|
||||
|
||||
|
||||
, h1 [ class "header" ] [ text "Control Unit" ]
|
||||
, p []
|
||||
[ div [class "input-row"]
|
||||
[ Html.label [ HAttr.for "cu-progcounter" ] [ text "Programm Counter:" ]
|
||||
, div [ class "input-group" ]
|
||||
[ button
|
||||
[ onClick <| PM_ManualStep UA_InstructionReg2ProgrammCounter ]
|
||||
[ text "InstRA -> " ]
|
||||
, Html.input
|
||||
[ HAttr.type_ "number"
|
||||
, HAttr.id "cu-progcounter"
|
||||
, value (addLeadingZero model.pc.programmCounter 3)
|
||||
, onInput PM_F_CuProgCounterEdit
|
||||
] []
|
||||
]
|
||||
]
|
||||
|
||||
, div [class "input-row"]
|
||||
[ Html.label [ HAttr.for "cu-instrReg" ] [ text "Instruction Register:" ]
|
||||
, div []
|
||||
[ Html.input
|
||||
[ HAttr.type_ "number"
|
||||
, HAttr.id "cu-instrReg"
|
||||
, class "instruction"
|
||||
, value (addLeadingZero instrRegInst 3)
|
||||
, onInput PM_F_CuInstrRegEditInstr
|
||||
] []
|
||||
, Html.input
|
||||
[ HAttr.type_ "number"
|
||||
, HAttr.id "cu-instrReg"
|
||||
, class "address"
|
||||
, value (addLeadingZero instrRegAddr 5)
|
||||
, onInput PM_F_CuInstrRegEditAddr
|
||||
] []
|
||||
]
|
||||
]
|
||||
|
||||
, div [class "input-row"]
|
||||
[ Html.label [ HAttr.for "cu-uCounter" ] [ text "µCode Counter:" ]
|
||||
, div [ class "input-group" ]
|
||||
[ button
|
||||
[ onClick <| PM_ManualStep UA_InstructionReg2UCounter ]
|
||||
[ text "IntrRI ->" ]
|
||||
, Html.input
|
||||
[ HAttr.type_ "number"
|
||||
, HAttr.id "cu-uCounter"
|
||||
, value (addLeadingZero model.pc.uCounter 4)
|
||||
, onInput PM_F_CuUCounterEdit
|
||||
] []
|
||||
]
|
||||
]
|
||||
]
|
||||
, div [ class "scroller" ]
|
||||
[ viewCuUCode model
|
||||
]
|
||||
--, div [ class "arrow", class "up"]
|
||||
-- [ div [ class "button" ]
|
||||
-- [ Html.a [ onClick (MsgManualStep ActDataBus2InstructionReg) ] [ text "DB -> InstR" ]]
|
||||
-- , div [] []
|
||||
-- ]
|
||||
, drawArrow Bottom Up UA_DataBus2InstructionReg "DB -> InstR"
|
||||
]
|
||||
|
||||
|
||||
viewCuUCode : PC_Model -> Html PC_Msg
|
||||
viewCuUCode model =
|
||||
Html.table []
|
||||
[ Html.thead [ class "head" ]
|
||||
[ Html.tr []
|
||||
[ Html.th [ class "address" ] [ text "µCounter" ]
|
||||
, Html.th [] [ text "µCode" ]
|
||||
]
|
||||
]
|
||||
, lazy viewCuUCodeContent model
|
||||
]
|
||||
|
||||
|
||||
viewCuUCodeContent : PC_Model -> Html PC_Msg
|
||||
viewCuUCodeContent model =
|
||||
let
|
||||
list2table : Int -> UAction -> Html PC_Msg
|
||||
list2table id code =
|
||||
Html.tr
|
||||
[ classList [ ( "current", id == model.pc.uCounter ), ("empty", code == UA_Nothing) ] ]
|
||||
[ Html.td [ class "num" ] [ text (addLeadingZero id 4) ]
|
||||
, Html.td [] [ viewCuInstrSelect id code ]
|
||||
]
|
||||
|
||||
in
|
||||
Html.tbody []
|
||||
((Array.toList <| Array.indexedMap list2table model.uCodes)
|
||||
++
|
||||
[ Html.tr []
|
||||
[ Html.td [] []
|
||||
, Html.td []
|
||||
[ button
|
||||
[ onClick PM_B_CuAddBelow ]
|
||||
[ text "Add Entry"]
|
||||
]
|
||||
]
|
||||
]
|
||||
)
|
||||
|
||||
viewCuInstrSelect : Int -> UAction -> Html PC_Msg
|
||||
viewCuInstrSelect id current =
|
||||
let
|
||||
info2option uCode =
|
||||
Html.option
|
||||
[ HAttr.selected (uCode.variant == current)
|
||||
, HAttr.value uCode.id ]
|
||||
[ text uCode.label ]
|
||||
listOptions = List.map info2option uCodes
|
||||
in
|
||||
Html.select
|
||||
[ HEvent.on "change" ( JD.map (PM_F_CuEditAction id) selectCuValueDecoder) ]
|
||||
listOptions
|
||||
|
||||
viewInstrEntry : Int -> Html PC_Msg
|
||||
viewInstrEntry i =
|
||||
let
|
||||
(instruction, address) = seperateInstructionsEntry i
|
||||
in
|
||||
text ( (addLeadingZero instruction 3) ++ " " ++ (addLeadingZero address 5) )
|
||||
|
||||
-- #####################################################################
|
||||
-- #####################################################################
|
||||
|
||||
|
||||
|
||||
|
||||
-- #####################################################################
|
||||
-- ALU
|
||||
-- #####################################################################
|
||||
|
||||
|
||||
viewAlu : PC_Model -> Html PC_Msg
|
||||
viewAlu model =
|
||||
div [ class "section", class "alu" ]
|
||||
[ h1 [ class "header" ] [ text "ALU" ]
|
||||
, p []
|
||||
[ Html.label [ HAttr.for "alu-accumulator" ] [ text "Accumulator:" ]
|
||||
, Html.input
|
||||
[ HAttr.type_ "number"
|
||||
, HAttr.id "alu-accumulator"
|
||||
, value (addLeadingZero model.pc.accumulator 8)
|
||||
, onInput PM_F_AluEdit
|
||||
] []
|
||||
]
|
||||
, p []
|
||||
[ button [ onClick <| PM_ManualStep UA_AccumulatorIncrement ] [ text "Acc ++" ]
|
||||
, button [ onClick <| PM_ManualStep UA_AccumulatorDecrement ] [ text "Acc --" ]
|
||||
]
|
||||
, drawArrow Bottom Up UA_DataBus2Accumulator "DB -> ALU"
|
||||
, drawArrow Bottom Down UA_Accumulator2DataBus "ALU -> DB"
|
||||
--, div [ class "arrow", class "up"]
|
||||
-- [ div [ class "button" ]
|
||||
-- [ Html.a [ onClick (MsgManualStep ActDataBus2Accumulator)] [ text "DB -> ALU" ]]
|
||||
-- , div [] []
|
||||
-- ]
|
||||
--, div [ class "arrow", class "down"]
|
||||
-- [ div [ class "button" ]
|
||||
-- [ Html.a [ onClick (MsgManualStep ActAccumulator2DataBus)] [ text "ALU -> DB" ]]
|
||||
-- , div [] []
|
||||
-- ]
|
||||
]
|
||||
|
||||
-- #####################################################################
|
||||
-- Busses
|
||||
-- #####################################################################
|
||||
|
||||
viewDataBus : PC_Model -> Html PC_Msg
|
||||
viewDataBus model =
|
||||
div [ class "databus" ]
|
||||
[ Html.span [ class "label" ] [ text "Databus" ]
|
||||
, Html.span []
|
||||
[ Html.input
|
||||
[ HAttr.type_ "number"
|
||||
, value (addLeadingZero model.pc.dataBus 8)
|
||||
, onInput PM_F_EditDataBus
|
||||
] []
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
viewAddressBus : PC_Model -> Html PC_Msg
|
||||
viewAddressBus model =
|
||||
div [ class "addressbus" ]
|
||||
[ Html.span [ class "label" ] [ text "Addressbus" ]
|
||||
, Html.span []
|
||||
[ Html.input
|
||||
[ HAttr.type_ "number"
|
||||
, value (addLeadingZero model.pc.addressBus 3)
|
||||
, onInput PM_F_EditAddressBus
|
||||
] []
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
-- #####################################################################
|
||||
-- #####################################################################
|
||||
|
||||
|
||||
|
||||
-- #####################################################################
|
||||
-- Helpers
|
||||
-- #####################################################################
|
||||
|
||||
type Arrow_Pos = Top | Bottom
|
||||
type Arrow_Dir = Up | Down
|
||||
|
||||
drawArrow : Arrow_Pos -> Arrow_Dir -> UAction -> String -> Html PC_Msg
|
||||
drawArrow pos dir act str =
|
||||
div
|
||||
[ HAttr.classList
|
||||
[ ("arrow", True)
|
||||
, ("top", pos == Top)
|
||||
, ("up", dir == Up)
|
||||
, ("down", dir == Down)]
|
||||
]
|
||||
[ div [ class "button" ]
|
||||
[ Html.a
|
||||
[ onClick (PM_ManualStep act) ]
|
||||
[ text str ]
|
||||
]
|
||||
, div [] []
|
||||
]
|
||||
|
||||
|
||||
selectCuValueDecoder : JD.Decoder String
|
||||
selectCuValueDecoder =
|
||||
JD.field "target" ( JD.field "value" JD.string)
|
||||
|
||||
|
||||
-- #####################################################################
|
||||
-- #####################################################################
|
||||
-- Done.
|
||||
|
||||
|
Reference in New Issue
Block a user