dd415019c4
When the program starts, when the showBoot() function is launched, the screenMode is checked and the showPorts function is launched, which in turn executes the renderPorts() function in a loop. While renderPorts is running, the screenMode may change, for example to ShowLines (when showString() was run). It may turn out that the mode has changed, and the renderPorts method has not been fully executed ... in the future, it will draw its own graphics on the screen, although we do not expect to see them already, because. a regime change has occurred. I added checks inside the function before displaying.
228 lines
7.2 KiB
TypeScript
228 lines
7.2 KiB
TypeScript
/**
|
|
* Tagged image literal converter
|
|
*/
|
|
//% shim=@f4 helper=image::ofBuffer
|
|
//% groups=["0.,","1#*"]
|
|
function img(lits: any, ...args: any[]): Image { return null }
|
|
|
|
const screen = image.create(DAL.LCD_WIDTH, DAL.LCD_HEIGHT)
|
|
|
|
namespace _screen_internal {
|
|
//% shim=pxt::updateScreen
|
|
function updateScreen(img: Image): void { }
|
|
//% shim=pxt::updateStats
|
|
function updateStats(msg: string): void { }
|
|
|
|
control.__screen.setupUpdate(() => updateScreen(screen))
|
|
control.EventContext.onStats = function (msg: string) {
|
|
updateStats(msg);
|
|
}
|
|
}
|
|
|
|
namespace brick {
|
|
const textOffset = 4;
|
|
const lineOffset = 2;
|
|
|
|
enum ScreenMode {
|
|
None,
|
|
ShowLines,
|
|
Image,
|
|
Ports,
|
|
Custom
|
|
}
|
|
|
|
let screenMode = ScreenMode.None;
|
|
export let font = image.font8;
|
|
|
|
/**
|
|
* Gets the text line height
|
|
*/
|
|
//%
|
|
export function lineHeight(): number {
|
|
return font.charHeight + lineOffset;
|
|
}
|
|
|
|
/**
|
|
* Number of lines
|
|
*/
|
|
//%
|
|
export function lineCount(): number {
|
|
return ((screen.height - textOffset) / lineHeight()) >> 0
|
|
}
|
|
|
|
/**
|
|
* Show text on the screen at a specific line.
|
|
* @param text the text to print on the screen, eg: "Hello world"
|
|
* @param line the line number to print the text at (starting at 1), eg: 1
|
|
*/
|
|
//% blockId=screen_print block="show string %text|at line %line"
|
|
//% weight=98 group="Screen" inlineInputMode="inline" blockGap=8
|
|
//% help=brick/show-string
|
|
//% line.min=1 line.max=10
|
|
export function showString(text: string, line: number) {
|
|
if (screenMode != ScreenMode.ShowLines) {
|
|
screenMode = ScreenMode.ShowLines;
|
|
screen.fill(0);
|
|
}
|
|
|
|
// line indexing starts at 1.
|
|
line = (line - 1) >> 0;
|
|
const nlines = lineCount();
|
|
if (line < 0 || line > nlines) return; // out of screen
|
|
|
|
const h = lineHeight();
|
|
const y = textOffset + h * line;
|
|
screen.fillRect(0, y, screen.width, h, 0); // clear background
|
|
screen.print(text, textOffset, y, 1, font);
|
|
}
|
|
|
|
/**
|
|
* Show a number on the screen
|
|
* @param value the numeric value
|
|
* @param line the line number to print the text at, eg: 1
|
|
*/
|
|
//% blockId=screenShowNumber block="show number %name|at line %line"
|
|
//% weight=96 group="Screen" inlineInputMode="inline" blockGap=8
|
|
//% help=brick/show-number
|
|
//% line.min=1 line.max=10
|
|
export function showNumber(value: number, line: number) {
|
|
showString("" + value, line);
|
|
}
|
|
|
|
/**
|
|
* Show a name, value pair on the screen
|
|
* @param value the numeric value
|
|
* @param line the line number to print the text at, eg: 1
|
|
*/
|
|
//% blockId=screenShowValue block="show value %name|= %text|at line %line"
|
|
//% weight=96 group="Screen" inlineInputMode="inline" blockGap=8
|
|
//% help=brick/show-value
|
|
//% line.min=1 line.max=10
|
|
export function showValue(name: string, value: number, line: number) {
|
|
value = Math.round(value * 1000) / 1000;
|
|
showString((name ? name + ": " : "") + value, line);
|
|
}
|
|
|
|
/**
|
|
* Show an image on the screen
|
|
* @param image image to draw
|
|
* @param duration duration in milliseconds to display the image, eg: 400
|
|
*/
|
|
//% blockId=screen_show_image block="show image %image=screen_image_picker"
|
|
//% weight=100 group="Screen" blockGap=8
|
|
//% help=brick/show-image
|
|
export function showImage(image: Image, duration: number = 400) {
|
|
if (!image) return;
|
|
screenMode = ScreenMode.Image;
|
|
screen.fill(0);
|
|
screen.drawImage(image, 0, 0);
|
|
if (duration > 0)
|
|
pause(duration);
|
|
}
|
|
|
|
/**
|
|
* Display the status of the sensors and motors attached to ports
|
|
*/
|
|
//% blockId=brickShowPorts block="show ports"
|
|
//% help=brick/show-ports blockGap=8
|
|
//% weight=10 group="Screen"
|
|
export function showPorts() {
|
|
if (screenMode == ScreenMode.Ports) return;
|
|
screenMode = ScreenMode.Ports;
|
|
|
|
renderPorts();
|
|
control.runInParallel(function () {
|
|
while (screenMode == ScreenMode.Ports) {
|
|
renderPorts();
|
|
pause(50);
|
|
}
|
|
})
|
|
}
|
|
|
|
function renderPorts() {
|
|
const col = 44;
|
|
const lineHeight8 = image.font8.charHeight + 2;
|
|
const h = screen.height;
|
|
|
|
clearScreen();
|
|
|
|
for (let i = 0; i < 4; ++i) {
|
|
const x = i * col + 2;
|
|
if (screenMode != ScreenMode.Ports) return;
|
|
screen.print("ABCD"[i], x, 1 * lineHeight8, 1, image.font8);
|
|
screen.print((i + 1).toString(), x, h - lineHeight8, 1, image.font8);
|
|
}
|
|
|
|
if (screenMode != ScreenMode.Ports) return;
|
|
screen.drawLine(0, 5 * lineHeight8, screen.width, 5 * lineHeight8, 1);
|
|
screen.drawLine(0, h - 5 * lineHeight8, screen.width, h - 5 * lineHeight8, 1);
|
|
|
|
function scale(x: number) {
|
|
if (Math.abs(x) >= 5000) {
|
|
const k = Math.floor(x / 1000);
|
|
const r = Math.round((x - 1000 * k) / 100);
|
|
return `${k}.${r}k`
|
|
}
|
|
return ("" + (x || 0));
|
|
}
|
|
|
|
// motors
|
|
const datas = motors.getAllMotorData();
|
|
for (let i = 0; i < datas.length; ++i) {
|
|
const data = datas[i];
|
|
const x = i * col + 2;
|
|
if (!data.actualSpeed && !data.count) continue;
|
|
if (screenMode != ScreenMode.Ports) return;
|
|
screen.print(`${scale(data.actualSpeed)}%`, x, 3 * lineHeight8, 1, image.font8);
|
|
screen.print(`${scale(data.count)}>`, x, 4 * lineHeight8, 1, image.font8);
|
|
}
|
|
|
|
// sensors
|
|
const sis = sensors.internal.getActiveSensors();
|
|
for (let i = 0; i < sis.length; ++i) {
|
|
const si = sis[i];
|
|
const x = (si.port() - 1) * col + 2;
|
|
const inf = si._info();
|
|
if (screenMode != ScreenMode.Ports) return;
|
|
if (inf) screen.print(inf, x, h - 2 * lineHeight8, 1, inf.length > 4 ? image.font5 : image.font8);
|
|
}
|
|
}
|
|
|
|
export function showBoot() {
|
|
// pulse green, play startup sound, turn off light
|
|
brick.setStatusLight(StatusLight.GreenPulse);
|
|
// We pause to give time to read sensor values, so they work in on_start block
|
|
pause(400); // It turns out that this time is not enough for the simulator to display the LED change
|
|
// and we're ready
|
|
brick.setStatusLight(StatusLight.Off);
|
|
// always show port by default if no UI is set
|
|
control.runInParallel(function () {
|
|
// show ports if nothing is has been shown
|
|
if (screenMode != ScreenMode.None) return;
|
|
showPorts();
|
|
})
|
|
}
|
|
|
|
/**
|
|
* An image
|
|
* @param image the image
|
|
*/
|
|
//% blockId=screen_image_picker block="%image" shim=TD_ID
|
|
//% image.fieldEditor="images"
|
|
//% image.fieldOptions.columns=6
|
|
//% image.fieldOptions.width=600
|
|
//% group="Screen" weight=0 blockHidden=1
|
|
export function __imagePicker(image: Image): Image {
|
|
return image;
|
|
}
|
|
|
|
/**
|
|
* Clear the screen
|
|
*/
|
|
//% blockId=screen_clear_screen block="clear screen"
|
|
//% weight=90 group="Screen"
|
|
//% help=brick/clear-screen weight=1
|
|
export function clearScreen() {
|
|
screen.fill(0)
|
|
}
|
|
} |