Skip to content
This repository was archived by the owner on Dec 8, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
cfd7a63
some renamings
pelikhan Jul 22, 2023
8667908
Merge remote-tracking branch 'origin/main' into ledserver
pelikhan Jul 22, 2023
f561c26
adding led driver
pelikhan Jul 22, 2023
7c96ddb
unused function
pelikhan Jul 22, 2023
08570a1
more led functionalities
pelikhan Jul 22, 2023
8e26d9f
porting some function
pelikhan Jul 22, 2023
654f73c
fixed setall
pelikhan Jul 22, 2023
49369ee
add large number of LEDs example
pelikhan Jul 22, 2023
41ea226
send image buffer if needed
pelikhan Jul 22, 2023
0ec4ec7
add TODO
pelikhan Jul 22, 2023
56e84f1
docs on socket limitations
pelikhan Jul 22, 2023
769b5ab
move display dimmer
pelikhan Jul 22, 2023
8334918
fix weird verif error
pelikhan Jul 22, 2023
7d52c5f
fix samples
pelikhan Jul 22, 2023
ea406ab
test verification
pelikhan Jul 22, 2023
7ab1ee0
undo
pelikhan Jul 22, 2023
88b4261
updated jacdac-ts
pelikhan Jul 22, 2023
d82d1d4
added LED display
pelikhan Jul 23, 2023
6acabfc
allocate palette auto
pelikhan Jul 23, 2023
0072b8d
move to functions for tree shacking
pelikhan Jul 23, 2023
3f8e12a
add gamma correction
pelikhan Jul 23, 2023
3b1635e
split led display
pelikhan Jul 23, 2023
90ce385
reduce import sizes
pelikhan Jul 23, 2023
6116501
move led to runtime
pelikhan Jul 23, 2023
06c24f7
Merge remote-tracking branch 'origin/main' into ledserver
pelikhan Jul 23, 2023
8fc0c9c
getting started on docs
pelikhan Jul 23, 2023
2c57c90
more docs
pelikhan Jul 23, 2023
3954a1c
more docs
pelikhan Jul 23, 2023
50f9069
more docs
pelikhan Jul 23, 2023
2f8c04a
reorg docs
pelikhan Jul 23, 2023
d0956c3
fix sample
pelikhan Jul 23, 2023
a0571e2
little disclaimer
pelikhan Jul 23, 2023
c0e212d
fix sample
pelikhan Jul 23, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cli/src/snippets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export async function snippets(options: SnippetsOptions) {
await writeFile(fullname, snip)
imports += `import "./${mod}"\n`
numsnip++
if (numsnip % 150 == 0) {
if (numsnip % 100 == 0) {
allImports.push(imports)
imports = ""
}
Expand Down
3 changes: 1 addition & 2 deletions compiler/src/specgen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -460,8 +460,7 @@ This service is ${status} and may change in the future.
`
: undefined,
patchLinks(info.notes["short"]),
`- client for [${info.name} service](https://microsoft.github.io/jacdac-docs/services/${info.shortId}/)`,
baseclass ? `- inherits ${baseclass}` : undefined,
`\n{@import optional ../clients-custom/${info.shortId}-short.mdp}\n`,
info.notes["long"]
? `## About

Expand Down
2 changes: 1 addition & 1 deletion jacdac-ts
1 change: 0 additions & 1 deletion packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import "./array"
import "./string"
import "./events"
import "./jacdac"
import "./led"
import "./lightbulb"
import "./rotaryencoder"
import "./button"
Expand Down
54 changes: 0 additions & 54 deletions packages/core/src/led.ts

This file was deleted.

1 change: 1 addition & 0 deletions packages/drivers/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ export * from "./dotmatrix"
export * from "./st7735"
export * from "./uc8151"
export * from "./trafficlight"
export * from "./ledserver"

configureHardware({ scanI2C: false })
144 changes: 144 additions & 0 deletions packages/drivers/src/ledserver.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
import * as ds from "@devicescript/core"
import {
PixelBuffer,
fillFade,
pixelBuffer,
correctGamma,
} from "@devicescript/runtime"
import { Server, ServerOptions, startServer } from "@devicescript/server"

export interface LedServerOptions {
/**
* Number of LEDs
*/
length: number
/**
* Brightness applied to pixels before being rendered.
* This allocate twice the memory if less than 1 as an additional buffer is needed to compute the color.
* @default 1
*/
intensity?: number
/**
* Number of columns of a LED matrix
*/
columns?: number
ledsPerPixel?: number
/**
* For monochrome LEDs, the LED wavelength
*/
waveLength?: number
/**
* The luminous power of the LEDs, is it very bright?
*/
luminousIntensity?: number
/**
* The shape and topology of the LEDs
*/
variant?: ds.LedVariant
/**
* Specify the amount of gamma correction
*/
gamma?: number
}

class LedServer extends Server implements ds.LedServerSpec {
private _intensity: number
private _columns: number
private _ledPerPixels: number
private _waveLength: number
private _luminousIntensity: number
private _variant: ds.LedVariant
private _gamma: number

readonly buffer: PixelBuffer

constructor(options: LedServerOptions & ServerOptions) {
super(ds.Led.spec, options)
this.buffer = pixelBuffer(options.length)
this._intensity = options.intensity ?? 1
this._columns = options.columns
this._ledPerPixels = options.ledsPerPixel
this._waveLength = options.waveLength
this._luminousIntensity = options.luminousIntensity
this._variant = options.variant
this._gamma = options.gamma
}

pixels(): ds.Buffer {
if (this.buffer.length < 64) return this.buffer.buffer
else return Buffer.alloc(0)
}
set_pixels(value: ds.Buffer): void {
this.buffer.buffer.blitAt(0, value, 0, value.length)
}
intensity(): number {
return this._intensity
}
set_intensity(value: number): void {
this._intensity = Math.clamp(0, value, 1)
}
actualBrightness(): number {
return this._intensity
}
numPixels(): number {
return this.buffer.length
}
numColumns(): number {
return this._columns
}
ledsPerPixel(): number {
return this._ledPerPixels
}
waveLength(): number {
return this._waveLength || 0
}
luminousIntensity(): number {
return this._luminousIntensity
}
variant(): ds.LedVariant {
return this._variant
}

/**
* Display buffer on hardware
*/
async show(): Promise<void> {
let b = this.buffer
// full brightness so we can use the buffer as is
if (this._intensity < 1 || this._gamma) {
const r = b.allocClone()
if (this._intensity < 1) fillFade(r, this._intensity)
if (this._gamma) correctGamma(r, this._gamma)
b = r
}
// TODO: render b to hardware
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mmoskal this is the part missing

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

}
}

/**
* Starts a programmable LED server.
* Simulation is supported for up to 64 LEDs; otherwise only the simulator
* will reflect the state of LEDs.
* @param options
* @returns
*/
export async function startLed(
options: LedServerOptions & ServerOptions
): Promise<ds.Led> {
const { length } = options
const server = new LedServer(options)
const client = new ds.Led(startServer(server))

;(client as any)._buffer = server.buffer
client.show = async function () {
await server.show()
if (length <= 64) await client.pixels.write(server.buffer.buffer)
else if (ds.isSimulator()) {
// the simulator handles brightness separately
const topic = `jd/${server.serviceIndex}/leds`
await ds._twinMessage(topic, server.buffer.buffer)
}
}

return client
}
8 changes: 4 additions & 4 deletions packages/graphics/src/image.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,14 @@ export declare class Image {
buffer: Buffer

/**
* Get a pixel color
* Return a copy of the current image
*/
get(x: number, y: number): number
clone(): Image

/**
* Return a copy of the current image
* Get a pixel color
*/
clone(): Image
get(x: number, y: number): number

/**
* Set pixel color
Expand Down
61 changes: 44 additions & 17 deletions packages/graphics/src/palette.ts
Original file line number Diff line number Diff line change
@@ -1,55 +1,82 @@
export class Palette {
readonly buffer: Buffer
readonly numColors: number
/**
* Number of colors in the palette
*/
readonly length: number

/**
* Allocates a 4bpp palette similar to MakeCode Arcade
* @returns
*/
static arcade() {
return new Palette(hex`
000000 ffffff ff2121 ff93c4 ff8135 fff609 249ca3 78dc52
003fad 87f2ff 8e2ec4 a4839f 5c406c e5cdc4 91463d 000000
`)
}

/**
* Allocates a 1bpp monochrome palette
* @returns
*/
static monochrome() {
return new Palette(hex`000000 ffffff`)
}

constructor(init: Buffer) {
this.buffer = init.slice(0)
this.buffer.set(init)
this.numColors = (this.buffer.length / 3) >> 0
this.length = (this.buffer.length / 3) >> 0
}

color(idx: number) {
if (idx < 0 || idx >= this.numColors) return 0
/**
* Returns the 24bit RGB color at the given index
* @param index
* @returns
*/
getAt(index: number) {
if (index < 0 || index >= this.length) return 0
return (
(this.buffer[3 * idx + 0] << 16) |
(this.buffer[3 * idx + 1] << 8) |
(this.buffer[3 * idx + 2] << 0)
(this.buffer[3 * index] << 16) |
(this.buffer[3 * index + 1] << 8) |
(this.buffer[3 * index + 2] << 0)
)
}

setColor(idx: number, color: number) {
this.buffer[3 * idx + 0] = color >> 16
this.buffer[3 * idx + 1] = color >> 8
this.buffer[3 * idx + 2] = color >> 0
/**
* Sets a 24bit RGB color at the given index
* @param index
* @param color 24bit RGB color
*/
setAt(index: number, color: number) {
this.buffer[3 * index] = color >> 16
this.buffer[3 * index + 1] = color >> 8
this.buffer[3 * index + 2] = color >> 0
}

// r,g,b,padding
/**
* Packs palette for Jacdac packet
* @returns
*/
packed(): Buffer {
const res: Buffer = Buffer.alloc(this.numColors << 2)
for (let i = 0; i < this.numColors; ++i) {
const res: Buffer = Buffer.alloc(this.length << 2)
for (let i = 0; i < this.length; ++i) {
res[i * 4] = this.buffer[i * 3]
res[i * 4 + 1] = this.buffer[i * 3 + 1]
res[i * 4 + 2] = this.buffer[i * 3 + 2]
}
return res
}

// r,g,b,padding
/**
* Unpacks palette from Jacdac packet
* @param buffer
*/
unpack(buffer: Buffer) {
if (buffer.length >> 2 !== this.numColors)
if (buffer.length >> 2 !== this.length)
throw new RangeError("incorrect number of colors")
for (let i = 0; i < this.numColors; ++i) {
for (let i = 0; i < this.length; ++i) {
this.buffer[i * 3] = buffer[i * 4]
this.buffer[i * 3 + 1] = buffer[i * 4 + 1]
this.buffer[i * 3 + 2] = buffer[i * 4 + 2]
Expand Down
Loading