Integrate RPI-configurator in menu

This commit is contained in:
Michał Moskal 2019-11-20 18:05:04 -08:00
Родитель 08c2c7ef09
Коммит a6aa037517
3 изменённых файлов: 424 добавлений и 130 удалений

266
main.ts
Просмотреть файл

@ -1,141 +1,151 @@
let admin = false;
let menuelts: string[] = [];
let cursor = 0;
let offset = 0;
let bcount = 0;
const logo = img`
. . 3 . . . 3 3 3 . . . 3 . . . 1 . . . 1 . 1 1 1 . 1 . 1 . 1 1 1 . 1 1 1 . 1 1 1 . 1 1 . . 1 1 1
. 3 . . . . . 3 . . . . . 3 . . 1 1 . 1 1 . 1 . 1 . 1 1 . . 1 . . . 1 . . . 1 . 1 . 1 . 1 . 1 . .
. 3 . . 3 3 3 3 3 3 3 . . 3 . . 1 . 1 . 1 . 1 1 1 . 1 . 1 . 1 1 . . 1 . . . 1 . 1 . 1 . 1 . 1 1 .
. 3 . . 3 3 3 3 3 3 3 . . 3 . . 1 . . . 1 . 1 . 1 . 1 . 1 . 1 1 1 . 1 1 1 . 1 1 1 . 1 1 . . 1 1 1
. 3 . . 3 3 3 3 3 . 3 . . 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3 . . . 3 3 3 3 3 . . . . . 3 . . 1 1 1 . . 1 1 1 1 . . . 1 1 1 . . . 1 1 1 . . 1 1 1 . . 1 1 1 1
. 3 . . 3 3 3 3 3 . 3 . . 3 . . 1 . . . 1 . 1 . . . 1 . 1 . . . 1 . 1 . . . 1 . 1 . . 1 . 1 . . .
. 3 . . 3 3 3 3 3 3 3 . . 3 . . 1 . . . 1 . 1 . . . 1 . 1 . . . . . 1 . . . 1 . 1 . . 1 . 1 . . .
. 3 . . 3 3 3 3 3 3 3 . . 3 . . 1 1 1 1 1 . 1 1 1 1 . . 1 . . . . . 1 1 1 1 1 . 1 . . 1 . 1 1 1 .
. 3 . . . . . . . . . . . 3 . . 1 . . . 1 . 1 . . . 1 . 1 . . . 1 . 1 . . . 1 . 1 . . 1 . 1 . . .
. . 3 . . . . . . . . . 3 . . . 1 . . . 1 . 1 . . . 1 . . 1 1 1 . . 1 . . . 1 . 1 1 1 . . 1 1 1 1
`
function move(dx: number) {
let nc = cursor + dx
if (nc < 0) nc = 0
else if (nc >= menuelts.length) nc = menuelts.length - 1
if (nc - offset < 2) offset = nc - 2
if (nc - offset > 5) offset = nc - 5
if (offset < 0) offset = 0
cursor = nc
}
function select() {
control.runProgram(menuelts[cursor])
}
function del() {
if (!admin) return;
const name = menuelts[cursor];
if (game.ask(`delete ${name}`, `are you sure?`)) {
control.deleteProgram(name);
menuelts.removeAt(0);
move(0);
function gameMenu() {
let admin = false;
let menuelts: string[] = [];
let cursor = 0;
let offset = 0;
let bcount = 0;
const logo = img`
. . 3 . . . 3 3 3 . . . 3 . . . 1 . . . 1 . 1 1 1 . 1 . 1 . 1 1 1 . 1 1 1 . 1 1 1 . 1 1 . . 1 1 1
. 3 . . . . . 3 . . . . . 3 . . 1 1 . 1 1 . 1 . 1 . 1 1 . . 1 . . . 1 . . . 1 . 1 . 1 . 1 . 1 . .
. 3 . . 3 3 3 3 3 3 3 . . 3 . . 1 . 1 . 1 . 1 1 1 . 1 . 1 . 1 1 . . 1 . . . 1 . 1 . 1 . 1 . 1 1 .
. 3 . . 3 3 3 3 3 3 3 . . 3 . . 1 . . . 1 . 1 . 1 . 1 . 1 . 1 1 1 . 1 1 1 . 1 1 1 . 1 1 . . 1 1 1
. 3 . . 3 3 3 3 3 . 3 . . 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3 . . . 3 3 3 3 3 . . . . . 3 . . 1 1 1 . . 1 1 1 1 . . . 1 1 1 . . . 1 1 1 . . 1 1 1 . . 1 1 1 1
. 3 . . 3 3 3 3 3 . 3 . . 3 . . 1 . . . 1 . 1 . . . 1 . 1 . . . 1 . 1 . . . 1 . 1 . . 1 . 1 . . .
. 3 . . 3 3 3 3 3 3 3 . . 3 . . 1 . . . 1 . 1 . . . 1 . 1 . . . . . 1 . . . 1 . 1 . . 1 . 1 . . .
. 3 . . 3 3 3 3 3 3 3 . . 3 . . 1 1 1 1 1 . 1 1 1 1 . . 1 . . . . . 1 1 1 1 1 . 1 . . 1 . 1 1 1 .
. 3 . . . . . . . . . . . 3 . . 1 . . . 1 . 1 . . . 1 . 1 . . . 1 . 1 . . . 1 . 1 . . 1 . 1 . . .
. . 3 . . . . . . . . . 3 . . . 1 . . . 1 . 1 . . . 1 . . 1 1 1 . . 1 . . . 1 . 1 1 1 . . 1 1 1 1
`
const move = (dx: number) => {
let nc = cursor + dx
if (nc < 0) nc = 0
else if (nc >= menuelts.length) nc = menuelts.length - 1
if (nc - offset < 2) offset = nc - 2
if (nc - offset > 5) offset = nc - 5
if (offset < 0) offset = 0
cursor = nc
}
}
function showMenu() {
menuelts = control.programList()
menuelts = menuelts.filter(s => s && s[0] != ".")
const select = () => {
control.runProgram(menuelts[cursor])
}
cursor = 0
offset = 0
const del = () => {
if (!admin) return;
const name = menuelts[cursor];
if (game.ask(`delete ${name}`, `are you sure?`)) {
control.deleteProgram(name);
menuelts.removeAt(0);
move(0);
}
}
function showMenu() {
menuelts = control.programList()
menuelts = menuelts.filter(s => s && s[0] != ".")
cursor = 0
offset = 0
controller.down.onEvent(ControllerButtonEvent.Pressed, function () {
move(1)
})
controller.down.onEvent(ControllerButtonEvent.Repeated, function () {
move(1)
})
controller.down.onEvent(ControllerButtonEvent.Pressed, function () {
move(1)
})
controller.down.onEvent(ControllerButtonEvent.Repeated, function () {
move(1)
})
controller.up.onEvent(ControllerButtonEvent.Pressed, function () {
move(-1)
})
controller.up.onEvent(ControllerButtonEvent.Repeated, function () {
move(-1)
})
controller.up.onEvent(ControllerButtonEvent.Pressed, function () {
move(-1)
})
controller.up.onEvent(ControllerButtonEvent.Repeated, function () {
move(-1)
})
controller.A.onEvent(ControllerButtonEvent.Pressed, function () {
select()
})
controller.A.onEvent(ControllerButtonEvent.Pressed, function () {
select()
})
controller.B.onEvent(ControllerButtonEvent.Pressed, function () {
control.runInBackground(del)
})
controller.B.onEvent(ControllerButtonEvent.Pressed, function () {
control.runInBackground(del)
})
game.onPaint(function () {
screen.fillRect(0, 0, 160, 20, 12)
screen.drawTransparentImage(logo, 4, 4)
for (let i = 0; i < 9; ++i) {
let e = menuelts[i + offset] || "";
e = e.split('_').join(' ')
e = e.split('-').join(' ')
let y = 25 + i * 11
if (i + offset == cursor) {
screen.fillRect(0, y - 2, 160, 11, 5)
screen.print(e, 10, y, 15)
game.onPaint(function () {
screen.fillRect(0, 0, 160, 20, 12)
screen.drawTransparentImage(logo, 4, 4)
for (let i = 0; i < 9; ++i) {
let e = menuelts[i + offset] || "";
e = e.split('_').join(' ')
e = e.split('-').join(' ')
let y = 25 + i * 11
if (i + offset == cursor) {
screen.fillRect(0, y - 2, 160, 11, 5)
screen.print(e, 10, y, 15)
}
else
screen.print(e, 10, y, 1)
}
else
screen.print(e, 10, y, 1)
}
})
})
}
const menuBootSequence = new storyboard.BootSequence(done => {
let phase = 0
let lg = swarm.swarmInSprite(logo, 100, 0.5, () => {
phase = 1
});
game.onUpdate(function () {
if (!phase)
return
if (phase++ == 10) {
phase = 20
lg.vy = -100;
lg.ay = 100;
lg.vx = -103;
lg.ax = 103;
}
if (lg.top <= 4 && done) {
done();
done = undefined;
}
})
}, 0);
scene.systemMenu.addEntry(
() => !admin ? "SHOW ADMIN MODE" : "HIDE ADMIN MODE",
() => admin = !admin
, img`
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . c c c c c c c . . . . .
. . . c c . . . . . c c c . . .
. . c c . . . . . . . . c c . .
. c c . . c c c c c . . . c . .
. c c c c c c c c c c c c c c .
. . c . c . c . c . c . c . . .
. . c . c . c . c . c . c . . .
. . c . c . c . c . c . c . . .
. . c . c . c . c . c . c . . .
. . c . c . c . . . c . c . . .
. . c . . . c . . . c . c . . .
. . c . . . . . . . . . c . . .
. . c c c c c c c c c c c . . .
. . . . . . . . . . . . . . . .
`)
storyboard.microsoftBootSequence.register()
menuBootSequence.register();
storyboard.registerScene("menu", showMenu)
storyboard.start()
}
const menuBootSequence = new storyboard.BootSequence(done => {
let phase = 0
let lg = swarm.swarmInSprite(logo, 100, 0.5, () => {
phase = 1
});
game.onUpdate(function () {
if (!phase)
return
if (phase++ == 10) {
phase = 20
lg.vy = -100;
lg.ay = 100;
lg.vx = -103;
lg.ax = 103;
}
if (lg.top <= 4 && done) {
done();
done = undefined;
}
})
}, 0);
scene.systemMenu.addEntry(
() => !admin ? "SHOW ADMIN MODE" : "HIDE ADMIN MODE",
() => admin = !admin
, img`
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . c c c c c c c . . . . .
. . . c c . . . . . c c c . . .
. . c c . . . . . . . . c c . .
. c c . . c c c c c . . . c . .
. c c c c c c c c c c c c c c .
. . c . c . c . c . c . c . . .
. . c . c . c . c . c . c . . .
. . c . c . c . c . c . c . . .
. . c . c . c . c . c . c . . .
. . c . c . c . . . c . c . . .
. . c . . . c . . . c . c . . .
. . c . . . . . . . . . c . . .
. . c c c c c c c c c c c . . .
. . . . . . . . . . . . . . . .
`)
storyboard.microsoftBootSequence.register()
menuBootSequence.register();
storyboard.registerScene("menu", showMenu)
storyboard.start()
if (!settings.readNumber("config-ok")) {
gameMenu()
} else {
rpiConfig()
}

Просмотреть файл

@ -12,11 +12,12 @@
"files": [
"README.md",
"main.ts",
"swarm.ts"
"swarm.ts",
"rpi-config.ts"
],
"testFiles": [
"test.ts"
],
"public": false,
"preferredEditor": "tsprj"
}
}

283
rpi-config.ts Normal file
Просмотреть файл

@ -0,0 +1,283 @@
function rpiConfig() {
// update this string with your arcade cfg if needed
const arcadeCfg = `
BTN_RESET=4
BTN_EXIT=3
BTN_MENU=2
BTN_A=26
BTN_B=19
BTN_LEFT=13
BTN_UP=6
BTN_RIGHT=5
BTN_DOWN=0
BTN_A2=11
BTN_B2=9
BTN_LEFT2=10
BTN_UP2=22
BTN_RIGHT2=27
BTN_DOWN2=17
BTN_A3=21
BTN_B3=20
BTN_LEFT3=16
BTN_UP3=12
BTN_RIGHT3=1
BTN_DOWN3=7
BTN_A4=8
BTN_B4=25
BTN_LEFT4=24
BTN_UP4=23
BTN_RIGHT4=18
BTN_DOWN4=15
`;
const pCols = [13, 3, 7, 9]
const bkg = image.create(160, 120);
bkg.fillRect(0, 10, 160, 66, 7)
for (let i = 0; i < 4; ++i) {
bkg.print((2 * i + 1).toString(), 154 - 8 * i, 44, 1);
bkg.print((2 * i + 2).toString(), 154 - 8 * i, 68, 1);
}
for (let i = 0; i < pCols.length; ++i) {
bkg.print("P" + (i + 1), 80 + i * (image.font8.charWidth * 3), 80, pCols[i]);
}
scene.setBackgroundImage(bkg)
const pinImg = img`
b b b b b b b b
b c c c c c c b
b c c c c c c b
b c c c c c c b
b c c c c c c b
b c c c c c c b
b c c c c c c b
b b b b b b b b
`
const bcmImg = img`
9 9 9 9 9 9 9 9
9 c c c c c c 9
9 c c c c c c 9
9 c c c c c c 9
9 c c c c c c 9
9 c c c c c c 9
9 c c c c c c 9
9 9 9 9 9 9 9 9
`
const pinSelectedImg = img`
1 1 1 1 1 1 1 1
1 5 5 5 5 5 5 1
1 5 5 5 5 5 5 1
1 5 5 5 5 5 5 1
1 5 5 5 5 5 5 1
1 5 5 5 5 5 5 1
1 5 5 5 5 5 5 1
1 1 1 1 1 1 1 1
`
const gndPinImg = img`
d d d d d d d d
d 1 1 f 1 1 1 d
d f f f f f 1 d
d 1 1 1 1 1 1 d
d 1 f f f 1 1 d
d 1 1 1 1 1 1 d
d 1 1 f 1 1 1 d
d d d d d d d d
`
const srcPinImg = img`
e e e e e e e e
e 2 2 2 2 2 2 e
e 2 2 2 f 2 2 e
e 2 2 2 f 2 2 e
e 2 f f f f f e
e 2 2 2 f 2 2 e
e 2 2 2 f 2 2 e
e e e e e e e e
`
bkg.drawImage(gndPinImg, 80, 90)
bkg.print("GND", 90, 90)
bkg.drawImage(srcPinImg, 80, 100)
bkg.print("+3.3/5V", 90, 100)
// BCM -> pin index
const bcmToPins: any = {
2: 3,
3: 5,
4: 7,
17: 11,
27: 13,
22: 15,
10: 19,
9: 21,
11: 23,
0: 27,
5: 29,
6: 31,
13: 33,
19: 35,
26: 37,
14: 8,
15: 10,
18: 12,
23: 16,
24: 18,
25: 22,
8: 24,
7: 26,
1: 28,
12: 32,
16: 36,
20: 38,
21: 40,
}
// ground pin indixes
const gnds = [6, 9, 14, 20, 25, 30, 34, 39];
const srcs = [1, 17, 2, 4]
let pinout: Sprite[] = []
for (let i = 0; i < 40; i++) {
const pin = sprites.create(pinImg.clone(), 0)
pin.data = {};
pinout.push(pin)
pin.left = 160 - ((i >> 1) + 1) * 8
if (i % 2 == 0) {
pin.y = 56
} else {
pin.y = 64
}
if (gnds.indexOf(pinout.length) > -1)
pin.setImage(gndPinImg);
if (srcs.indexOf(pinout.length) > -1)
pin.setImage(srcPinImg);
}
// parse arcade.cfg, store name in sprites
for (let line of arcadeCfg.split('\n')) {
if (line.indexOf("BTN_") != 0) continue;
const parts = line.substr(4).split('=');
const name = parts[0];
const bcm = parseInt(parts[1]);
const index = bcmToPins[bcm] as number;
const sprite = pinout[index - 1];
sprite.data["name"] = name;
sprite.setImage(bcmImg.clone());
if (name == "RESET") {
bkg.print(`RESET ${index}`, 10, 80, 10)
sprite.setImage(pinImg)
sprite.setImage(sprite.image.clone())
sprite.image.replace(0xc, 10);
}
else if (name == "EXIT") {
bkg.print(`EXIT ${index}`, 10, 90, 3)
sprite.setImage(pinImg)
sprite.setImage(sprite.image.clone())
sprite.image.replace(0xc, 3);
}
else if (name == "MENU") {
bkg.print(`MENU ${index}`, 10, 100, 4)
sprite.setImage(pinImg)
sprite.setImage(sprite.image.clone())
sprite.image.replace(0xc, 4);
} else {
const i = (parseInt(name[name.length - 1]) || 1) - 1;
sprite.image.print(name[0], 2, 2, pCols[i], image.font5)
}
}
// setup menu, reset, select
// text sprites
let buttonName = sprites.create(img`
. . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
. . . . . . . . . b 5 5 b . . .
. . . . . . b b b b b b . . . .
. . . . . b b 5 5 5 5 5 b . . .
. b b b b b 5 5 5 5 5 5 5 b . .
. b d 5 b 5 5 5 5 5 5 5 5 b . .
. . b 5 5 b 5 d 1 f 5 d 4 f . .
. . b d 5 5 b 1 f f 5 4 4 c . .
b b d b 5 5 5 d f b 4 4 4 4 b .
b d d c d 5 5 b 5 4 4 4 4 4 4 b
c d d d c c b 5 5 5 5 5 5 5 b .
c b d d d d d 5 5 5 5 5 5 5 b .
. c d d d d d d 5 5 5 5 5 d b .
. . c b d d d d d 5 5 5 b b . .
. . . c c c c c c c c b b . . .
`)
buttonName.x = 80
buttonName.y = 36
buttonName.say("Press buttons for pin INDEX")
let lastPress = 0
let lastKey = ""
let comboLen = 0
const select = (name: string) => {
const sprite = pinout.filter(pin => pin.data["name"] == name)[0];
const index = pinout.indexOf(sprite) + 1;
sprite.image.replace(0xc, 5)
buttonName.say(`${name} ${index}`, 0);
lastPress = control.millis()
if (name == "A") {
if (lastKey == "B") comboLen++
else comboLen = 1
} else if (name == "B") {
if (lastKey == "A") comboLen++
else comboLen = 0
} else {
comboLen = 0
}
if (comboLen >= 6) {
settings.writeNumber("config-ok", 1)
control.reset()
}
lastKey = name
}
const unselect = (name: string) => {
const sprite = pinout.filter(pin => pin.data["name"] == name)[0];
sprite.image.replace(5, 0xc)
buttonName.say("", 0);
lastPress = control.millis()
}
function setup(btn: controller.Button, name: string) {
btn.onEvent(ControllerButtonEvent.Pressed, function () { select(name) })
btn.onEvent(ControllerButtonEvent.Released, function () { unselect(name) });
}
game.onUpdateInterval(500, function () {
if (lastPress && control.millis() - lastPress > 5000) {
buttonName.say("Press A B A B A B when you're done!", 0);
lastPress = 0
}
})
// wire all events
setup(controller.A, "A");
setup(controller.B, "B");
setup(controller.up, "UP");
setup(controller.down, "DOWN");
setup(controller.left, "LEFT");
setup(controller.right, "RIGHT");
setup(controller.player2.A, "A2");
setup(controller.player2.B, "B2");
setup(controller.player2.up, "UP2");
setup(controller.player2.down, "DOWN2");
setup(controller.player2.left, "LEFT2");
setup(controller.player2.right, "RIGHT2");
setup(controller.player3.A, "A3");
setup(controller.player3.B, "B3");
setup(controller.player3.up, "UP3");
setup(controller.player3.down, "DOWN3");
setup(controller.player3.left, "LEFT3");
setup(controller.player3.right, "RIGHT3");
setup(controller.player4.A, "A4");
setup(controller.player4.B, "B4");
setup(controller.player4.up, "UP4");
setup(controller.player4.down, "DOWN4");
setup(controller.player4.left, "LEFT4");
setup(controller.player4.right, "RIGHT4");
}